Akhil
Akhil

Reputation: 2030

Zero to One Relationship in EF Code First

I have 2 entities like below;

public class Order
{
  public int Id { get; set; }
  public Description { get; set; }

 public virtual Purchase Purchase{ get; set;}
}

public class Purchase
{
 public int Id { get; set; }
 public Description { get; set;}
 public int? OrderId { get; set;}

 public virtual Order Order { get; set;}
}

Here I create order first.

  1. Based on order i can create purchase.
  2. Purchase can be happened without order also. So it is Nullable foreign key.
  3. For one order, it should have only one purchase. So OrderId is unique also.

How can i specify this relationship in Code First

Upvotes: 0

Views: 52

Answers (2)

CodingYoshi
CodingYoshi

Reputation: 27049

In the comments to your question, you indicated:

I need to make it (OrderId) unique also

You cannot do that that because EF does not support unique columns except keys.

You may use an index which will allow you to make the index unique but you cannot have a unique key.

Upvotes: 0

David Browne - Microsoft
David Browne - Microsoft

Reputation: 89424

You can specify a unique attribute like this. You just can't make a unique index the target of a foreign key in EF6.

public class Order
{
    public int Id { get; set; }
    public string Description { get; set; }
    public virtual Purchase Purchase { get; set; }
}

public class Purchase
{
    public int Id { get; set; }
    public string Description { get; set;}

    [Index(IsUnique = true)]
    public int? OrderId { get; set; }
    public virtual Order Order { get; set; }
}

But EF won't allow a 1-1 relationship to a non-key column, but something like this has the desired relational model:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp5
{
    public class Order
    {
        public int Id { get; set; }
        public string Description { get; set; }
        internal ICollection<Purchase> Purchases { get; } = new HashSet<Purchase>();
        public Purchase Purchase { get { return Purchases.FirstOrDefault(); } }
    }

    public class Purchase
    {
        public int Id { get; set; }
        public string Description { get; set; }

        [Index(IsUnique = true)]
        public int? OrderId { get; set; }

        [ForeignKey("OrderId")]
        public virtual Order Order { get; set; }
    }

    public class Db : DbContext
    {
        public DbSet<Order> Orders { get; set; }
        public DbSet<Purchase> Purchases { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Order>().HasMany(o => o.Purchases).WithOptional(p => p.Order);
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Database.SetInitializer(new DropCreateDatabaseAlways<Db>());
            int OrderId;
            using (var db = new Db())
            {

                var o = db.Orders.Create();
                o.Description = "New Order";

                var p = db.Purchases.Create();
                p.Order = o;
                p.Description = "New Purchase";


                db.Orders.Add(o);
                db.Purchases.Add(p);
                db.SaveChanges();
                OrderId = o.Id;

            }
            using (var db = new Db())
            {
                var p = db.Purchases.Create();
                p.OrderId = OrderId;
                p.Description = "Another Purchase";
                db.Purchases.Add(p);
                db.SaveChanges(); //fails

            }
        }
    }
}

David

Upvotes: 1

Related Questions