0

我正在使用 Entity Framework 并遇到了关于多对多映射的绊脚石。假设我有两个实体,订单和产品。

在我的 Order 实体中,我有:

int OrderID,
double OrderPrice
datetime OrderDate
ICollection<Product> Products
datetime DispactDate

等等...

然后在我的产品类中我有

int ProductID
string ProductName
string ProductDescription

等等。

在我的 Code First EF DB 中,我有一个订单表,它很好地映射到我的订单,一个产品表,其中包含可以订购的产品列表,然后使用 EF 代码优先迁移 EF 创建了带有外键的 OrderProducts 的两个主键其他表。都好。

但是,当我保存在其产品集合中有多个产品的订单时,EF 正在复制产品表中的所有条目。因此,如果我添加产品 10、12 和 13,它会使用三个新 ID 创建三个新行并映射到它们,而不是原来的。如果我随后处理另一个包含另外 20 个现有产品的订单,那么产品表中将创建 20 个新条目!

在我的 DBContext 中,我已经覆盖了 onModelCreatingEvent:

modelBuilder.Entity<Order>()
                .HasMany(x=>x.Products)
                .WithMany()
                .Map(be =>
                    {
                        be.ToTable("OrderProducts");
                });

我猜这里配置有问题。我从如何在实体框架 CTP5 中映射多对多关系?

以前我有两个独立的存储库——一个用于订单,一个用于产品。我现在已将这些合并到 orderRepository 中,它公开了 Orders 和 Products,以便我可以将产品附加到 orderRepository 上下文。为了生成产品,我有一个控制器操作 AddProducts:

public RedirectToRouteResult Products(FormCollection selectedProducts)
        {
                currentOrder.Products = new List<Product>();
                foreach (string thisProduct in selectedProducts)
                {
                    int thisProductID = int.Parse(thisProduct);
                    Product selectedProduct = orderRepository.Products.Where(e => e.ProductID == thisProductID).FirstOrDefault();

                    if (selectedProduct != null)
                    {
                        orderRepository.AttachToContext(selectedProduct);
                        currentOrder.Products.Add(selectedProduct);
                    }                    
                }

                orderRepository.saveChanges(currentOrder);

}

4

3 回答 3

1

我怀疑 inorderRepository您的上下文实例与 in 不同ProductsRepo。您应该首先产品附加到ProductsinorderRepository的上下文中。

顺便说一下,这是为什么每个实体的存储库会真正妨碍您的一个示例。如果您想使用存储库模式,通常最好考虑聚合根。

于 2012-08-03T21:09:10.060 回答
0

你能敲出一个小单元测试,它只创建上下文、检索产品、创建订单并将检索到的产品添加到订单中吗?

那应该工作得很好。听起来您正在创建一个新的产品对象,而不是使用预先存在的产品对象。或者创建一个而不设置适当的实体键。

这听起来不像是从不同的上下文中获取它,因为您通常会收到警告说它已经附加到另一个上下文。

于 2012-08-04T07:46:14.830 回答
0

谢谢。设法解决了这个问题。在我的OrderRepository我不得不手动标记每个Product状态EntitySate.Unchanged。所以,SaveOrder()我现在做:

foreach (Product product in Orders.Products)
{
  context.Entry(product).State = System.Data.EntityState.Unchanged;
}

这工作正常,但我很好奇为什么当订单中的每个产品都已经分配了一个有效的(和现有的)productid 时我必须执行此步骤?奇怪的。

于 2012-08-08T07:59:16.173 回答