C# 调用savechanges时Entityframework复制

C# 调用savechanges时Entityframework复制,c#,entity-framework,ef-code-first,C#,Entity Framework,Ef Code First,我首先使用entityframework 5代码,我有一个这样的模型 class Product { public Product() { Fabrics = new BindingList<FabricLineItem>(); } ... public virtual ICollection<FabricLineItem> Fabrics { get;set; } } class FabricLineItem {

我首先使用entityframework 5代码,我有一个这样的模型

class Product {
    public Product() {
        Fabrics = new BindingList<FabricLineItem>();
    }
    ...
    public virtual ICollection<FabricLineItem> Fabrics { get;set; }
}

class FabricLineItem {
    [ForeignKey("Fabric")]
    public int FabricId { get; set; }  
    public virtual Product Product { get;set; }
    public virtual Fabric Fabric { get;set; }  
}

class Fabric {
    ...
}

在调用savechanges之前,调试器中的值是否正确?在调用savechanges之后,调试器中的值是否已更改?知道我为什么会有这种奇怪的行为吗?

根据评论中的其他信息:您需要将FabricLineItemID(主键)添加到FabricLineItem类/实体中,并删除FabricId(EF将为您创建一个外键)。创建新的FabricLineItem时,要与产品关联,请从数据库中获取结构记录,然后将其与新创建的FabricLineItem关联,然后获取产品并将其与FabricLineItem关联。您不需要在产品的构造函数中创建新列表,EF将完成其余工作。

我怀疑上下文不知道结构不是新项目,因此它会添加/插入它们

如果将结构附加到DataContext(未更改/未修改)-或从数据库中选择它们,则当调用SaveChanges()时,上下文知道现有结构对象,然后可以仅为新FabricLineItem创建导航关系而不创建新结构


EF比它看起来要“愚蠢”得多-你真的需要告诉它几乎所有的事情。

我也遇到了E.F.在另一个要添加到DB的新对象中引用某个项时,无法识别该项已经存在的问题

@尼尔·汤普森向我提供了上述解决方法的线索:

您需要将现有实体附加到上下文,以便它知道它已经存在:

例如:

context.Fabrics.Attach(product.Fabric); 
context.Products.Add(product);
context.SaveChanges();

return organisation;
我从这里得到这个:

“如果您知道数据库中已经存在一个实体,但该实体当前未被上下文跟踪,那么您可以告诉上下文使用DbSet上的Attach方法跟踪该实体。该实体在上下文中将处于未更改状态。”


为什么在
FabricLineItem
中有
FabricId
virtual Fabric
?不仅仅是
虚拟结构
就足够了吗?如何将
FabricLineItems
添加到
产品
?首先,我只尝试了一下。。但后来我尝试显式设置fabricid,然后尝试保存,但也不起作用。您能告诉我们有关您尝试实现的实际数据模型的更多详细信息吗?什么是
FabricLineItem
?你能不能不把
面料
产品
联系起来?实际上,该产品将有一些面料[这些面料类似于原材料],因此我创建了一个fabriclineitem,它将面料链接到产品,并有一些字段,说明产品的哪个部分使用了多少面料。这就是你要问的?你的代码没有你如何保存它的部分。您需要获取结构对象非Id才能保存它。如果未加载结构对象,请仅使用id进行加载。id已存在。。在这里,您可以看到实际的类。你是说我应该先保存产品,然后保存行项目?实际上,我已经将这个模型与视图绑定在一起,这样产品屏幕就可以同时显示行项目列表和其他产品字段。哇,这比我想象的要复杂得多。但是,我认为如果您从
FabriLineItem
中丢失了
FabricId
,并确保您正在向产品添加一个现有结构(从DB检索到的结构),您应该不会有问题。另外,不要在产品的构造函数中创建新列表。我认为,当您将行项目添加到该列表时,实际上可能是在复制内存中的记录。保存时,EF将更改这些行项目的ID(在DB中创建新记录)。您不需要先保存产品-创建一个新产品,将其添加到新行项目中。这样就可以了。
context.Fabrics.Attach(product.Fabric); 
context.Products.Add(product);
context.SaveChanges();

return organisation;