2013-12-17 100 views
0

我之前問過類似的問題,但希望發佈一個更新的問題,包括所需的所有必要的代碼來說明:實體框架1:1的關係FK的

我有2個實體;購物車和購物者。他們有1:1的關係。有時候我不想加載導航屬性來讀取FK值。我創建瞭如下所述的實體並設置購物車和購物者之間的關係(請參閱下面的映射類),但是EF沒有在實體上填充FK屬性(請參閱下面的單元測試)。

using System; 
using System.Collections.Generic; 
using System.Data.Entity; 
using System.Data.Entity.ModelConfiguration; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using Microsoft.VisualStudio.TestTools.UnitTesting; 

namespace ClassLibrary1 
{ 
    public class Cart 
    { 
     public int ID { get; set; } 
     public int ShopperID { get; set; } 
     public virtual Shopper Shopper { get; set; } 
    } 

    public class Shopper 
    { 
     public int ID { get; set; } 
     public int CartID { get; set; } 
     public virtual Cart Cart { get; set; } 
    } 

    public class CartMap:EntityTypeConfiguration<Cart> 
    { 
     public CartMap() 
     { 
      this.HasKey(t => t.ID); 

      // Properties 

      // Table & Column Mappings 
      this.ToTable("Cart", "Cart2"); 
      this.Property(t => t.ID).HasColumnName("ID"); 
      this.Property(t => t.ShopperID).HasColumnName("ShopperID"); 
      //this.HasRequired(t => t.Shopper) 
      // .WithRequiredPrincipal(t => t.Cart); 
     } 

    } 

    public class ShopperMap : EntityTypeConfiguration<Shopper> 
    { 
     public ShopperMap() 
     { 
      this.HasKey(t => t.ID); 

      // Properties 

      // Table & Column Mappings 
      this.ToTable("Shopper", "Cart2"); 
      this.Property(t => t.ID).HasColumnName("ID"); 
      this.Property(t => t.CartID).HasColumnName("CartID"); 

      //// Relationships 
      this.HasRequired(t => t.Cart) 
       .WithRequiredDependent(t => t.Shopper) 
       .WillCascadeOnDelete(true); 
     } 
    } 

    public class CartDbContext : DbContext 
    { 
     public IDbSet<Cart> Carts { get; set; } 
     public IDbSet<Shopper> Shoppers { get; set; } 
     public CartDbContext():base("name=CartTest") 
     { 

     } 

     protected override void OnModelCreating(DbModelBuilder modelBuilder) 
     { 
      base.OnModelCreating(modelBuilder); 
      modelBuilder.Configurations.Add(new CartMap()); 
      modelBuilder.Configurations.Add(new ShopperMap()); 
     } 
    } 

    public class DBSeedingData : DropCreateDatabaseAlways<CartDbContext> 
    { 
     protected override void Seed(CartDbContext context) 
     { 
      var cart1 = new Cart{Shopper = new Shopper()}; 
      var cart2 = new Cart {Shopper = new Shopper()}; 
      base.Seed(context); 
      context.Carts.Add(cart1); 
      context.Carts.Add(cart2); 
      context.SaveChanges(); 
     } 
    } 

    [TestClass] 
    public class TestClass 
    { 
     [ClassInitialize] 
     public static void RunOnceForAllTests(TestContext testContext) 
     { 
      Console.WriteLine("Initializing Database"); 
      using (var ctx = new CartDbContext()) 
      { 
       try 
       { 
        Database.SetInitializer(new DBSeedingData()); 
        ctx.Database.Initialize(true); 
        Console.WriteLine("Database Dropped, Created & Seeded."); 
       } 
       catch (Exception ex) 
       { 
        throw ex; 
       } 
      } 
     } 
     [TestMethod] 
     public void CanReadAllCarts() 
     { 
      using (var ctx = new CartDbContext()) 
      { 
       foreach (var cart in ctx.Carts) 
       { 
        Console.WriteLine(" actual: Cart Id: {0} Shopper Id: {1} Shopper's Cart Id: {2}", cart.ID, cart.ShopperID, cart.Shopper.CartID); 
        Assert.IsTrue(cart.ID > 0, "Cart PK was not set"); 
        Assert.IsTrue(cart.ShopperID > 0, "Shopper FK in Cart was not set"); 
        Assert.IsNotNull(cart.Shopper, "Failed to load navigation properties"); 
        Assert.IsTrue(cart.Shopper.CartID > 0, "Cart FK in Shopper was not set"); 
       }  
      }  
     } 
    } 
} 

我在這裏錯過了什麼?我一直試圖解決這個問題一週。

回答

0

我以前經歷過這一點,也遇到了麻煩,做一對一的EF。我們做了一個工作,其中兩個實體之間只有一個導航屬性。在你的情況下,選擇是否將導航屬性放在Cart或Shopper類中。基本上,這是EF中的映射,其中只有一方具有導航屬性。缺點是沒有導航屬性的是盲目的,你不能分辨它與誰有關。這是關於它的article

比方說,你把導航屬性在購物類

public class Cart 
{ 
    public int ID { get; set; } 

    // no nav property for Shopper 
} 

public class Shopper 
{ 
    public int ID { get; set; } 
    public int CartID { get; set; } 
    public virtual Cart Cart { get; set; } 
} 

那麼你會像這樣映射它:

public class ShopperMap : EntityTypeConfiguration<Shopper> 
{ 
    public ShopperMap() 
    { 
     // other mappings 

     // mapping to cart, notice that the WithMany() is empty   
     this.HasRequired(t => t.Cart) 
      .WithMany() 
      .HasForeignKey(t => t.CartID); 
    } 
} 

你會在文章中看到,EF代碼優先(或一般EF)不支持一對一的外鍵關聯。這項工作爲我們工作,所以我希望它也適合你。

+0

Bairose - 感謝您的信息。我試圖在我的代碼中重現您的建議。在你的例子中,盲實體中的FK的值是否被設置(在你的例子中,Cart.ShopperID是否被設置?)。在我的代碼中,我讓購物者成爲盲人實體,並將購物車地圖中的關係設置爲: 'this.HasRequired(t => t.Shopper) .WithMany() .HasForeignKey(t => t.ShopperId );' ,但購物者的CartId值沒有設置。 – cdarrigo

+0

對不起,這是一個錯字。只是複製粘貼你的類..但是,不,Cart.ShopperID不應該在那裏。我現在編輯並刪除它。 – Bairose

+0

好吧,我現在刪除它,因爲你想購物者是盲目的實體只是刪除Shopper.CartId,我看到你的映射是正確的,所以你應該很好去。 Shopper.CartId永遠不會被設置,即使你把它放在那裏(對不起,我的不好),因爲我們使它成爲一個單向映射,所以EF只是將它視爲一個普通屬性而不是外鍵,因此只需將其刪除即可。 – Bairose