简体   繁体   English

实体框架1:1关系FK

[英]Entity Framework 1:1 Relationship FK's

I've asked a similar question before, but wanted to post an updated question and include all the necessary code required to illustrate: 我之前曾问过类似的问题,但想发布一个更新的问题,并包括所有必要的代码来说明:

I've got 2 entities; 我有2个实体; Cart and Shopper. 购物车和购物者。 They have a 1:1 relationship. 他们有1:1的关系。 There are times when I don't want to have to load up the nav properties to read the FK value. 有时候我不想加载nav属性来读取FK值。 I've created the entities as described below and set the relationship between cart and shopper (see mapping classes below) but EF is not populating the FK properties on the entities (see the unit test below). 我已经按如下所述创建了实体,并设置了购物车和购物者之间的关系(请参见下面的映射类),但是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");
                }    
            }    
        }
    }  
}

What am I missing here? 我在这里想念什么? I've been stuck trying to solve this problem for a week. 我一直在努力解决这个问题一个星期。

I've experienced this before and also had trouble doing one to one in EF. 我以前曾经经历过,并且在EF中一对一进行时也遇到了麻烦。 We did a work around wherein just have one navigation property between the two entities. 我们进行了一项工作,其中两个实体之间只有一个导航属性。 In your case, pick whether you would put the navigation property in Cart or Shopper class. 在您的情况下,选择是否将导航属性放在Cart或Shopper类中。 Basically, this is a mapping in EF where only one side has a nav property. 基本上,这是EF中的映射,其中只有一侧具有nav属性。 The downside is that the one with no nav property is blind and you can't tell who it's related to. 缺点是没有导航属性的人是盲人的,您无法分辨出它与谁有关。 Here's an article about it. 这是一篇关于它的文章

Let's say you put the nav property in the Shopper class 假设您将nav属性放在Shopper类中

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; }
}

then you'll map it like so: 然后您将其映射为:

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);
    }
}

You'll see in the article that EF Code-First (or EF in general) does not support one-to-one foreign key associations. 您会在文章中看到EF Code-First(或通常称为EF)不支持一对一的外键关联。 This work around worked for us so I hope it does for you too. 这项工作对我们有用,所以我希望对您也有用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM