gpt4 book ai didi

c# - Entity Framework 和添加 POCO,而不添加子对象

转载 作者:行者123 更新时间:2023-12-02 11:18:52 24 4
gpt4 key购买 nike

所以也许我解决这个问题的方式是错误的,但我想从 StackOverflow 上的优秀人士那里得到关于如何更正确地做到这一点的意见。

我有一个程序,它必须从 Entity Framework 6.0 代码优先上下文的存储库中检索信息,对所包含的信息进行一些处理,然后将新记录添加到数据库中。

无论如何,这是我通过存储库从 EF 检索的类的简化 View :

public class Product
{
public int Id { get;set; }
public virtual ProductCategory Category { get;set; }
public string Name { get;set; }
}

然后,我使用以下定义构建 ProcessedProduct,并将之前检索到的 Product 作为 BaseProduct 传递:

public class ProcessedProduct
{
public int Id { get;set; }
public virtual Product BaseProduct { get;set; }
}

我使用了我在 Pluralsight 上的 EF 类(class)中看到的存储库层,并专门用于此处。我添加了以下所有相关部分:

public class MyContext : BaseContext<MyContext>, IMyContext
{
//Lots of IDbSets for each context
public void SetModified(object entity)
{
Entry(entity).State = EntityState.Modified;
}

public void SetAdd(object entity)
{
Entry(entity).State = EntityState.Added;
}
}

public class MyRepository : IMyRepository
{
private readonly IMyContext _context;

public MyRepository(IUnitOfWork uow)
{
_context = uow.Context as IMyContext;
}

public ProcessedProduct FindProcessedProduct(int id)
{
return _context.ProcessedProducts.Find(id);
}

public ProductCategory FindCategory(int id)
{
return _context.Categories.Find(id);
}

public int AddProcessedProductWithoutProduct(ProcessedProduct newRecord)
{
newRecord.Product = null;
Save();
return newRecord.Id;
}

public int UpdateProcessedProductWithProductButWithoutChildProperties(int processedProductId, int productId)
{
var processedProduct = FindProcessedProduct(processedProductId);
processedProduct.BaseProduct = FindProduct(productId);
processedProduct.BaseProduct.Category = null;
_context.SetModified(product);
Save();

return processedProduct.Id;
}

public int UpdateProductChildren(int processedProductId, int categoryId)
{
var processedProduct = FindProcessedProduct(processedProductId);
var category = FindCategory(categoryId);
processedProduct.BaseProduct.Category = category;
_context.SetModified(product);
Save();

return processedProduct.Id;
}
}

最后,这是将所有内容组合在一起的部分:

try
{
//Create the processed product without the product instance
var processedProductId = repo.AddProcessedProductWithoutProduct(finishedProduct);

//Now, update this processed product record with the product. This way, we don't create a
//duplicate product.
processedProductId = repo.UpdateProcessedProductWithProductButWithoutChildProperties(processedProductId, product.Id);

//Finally, update the category
processedProductId = repo.UpdateProductChildren(processedProductId, product.Category.Id);

//Done!
}

当我尝试将此 ProcessedProduct 插入 EF 时,它会正确创建 ProcessedProduct 记录,但还会创建一个新的 Product 和新的 Category 行。我尝试手动更改每个对象的更改跟踪,以便 ProcessedProduct 将被“添加”,而其他对象将被“修改”或“未更改”,但我会收到 Entity Framework 抛出的外键引用异常。

我的“修复”是将其简单地分解为多个不同的调用:

  1. 我创建了新的 ProcessedProduct 记录,但将 Product 值指定为 null。
  2. 我使用 ID 查询该 ProcessedProduct 记录,使用其 Id 查询相应的产品,并将该产品分配给新检索的 ProcessedProduct 记录。但是,我必须将 Category 属性清空,否则这将添加新的重复 Category 记录。我保存并修改了 ProcessedProduct 记录。
  3. 最后,我再次查询 ProcessedProduct 以及 ProductCategory,然后将该 ProductCategory 分配给 ProcessedProduct.BaseProduct 的 Category 属性。我可以再次保存,现在我已经创建了我需要的所有记录,而无需进行任何重复。

但是,这种方法看起来相当复杂,因为我最初想做的就是保存新的父记录,而不是创建重复的子记录。有没有更好的方法来做我所缺少的事情?谢谢!

编辑:我想更大的问题是我有一个复杂的对象,其中包含一大堆这些子复杂对象。创建新父对象的最简单方法是什么,而无需遍历子对象的整个图表来一次一层地更新父对象?

最佳答案

我强烈建议在编辑时不要将“产品和类别”设置为导航属性。正如您所见,当您将已处理产品的图表(附加了产品和类别)添加到 EF 上下文时,它将图表中的所有内容标记为已添加,并对所有内容进行插入。我总是推荐的模式(Nikolai 也在他的评论中建议,所以像我一样对他的评论进行投票:))是在您的实体中包含 FK ID 并设置这些值,而不是导航。例如newRecord.ProductId=theProductIdValue。

很多人都哭过“但是外键?哎呀!它们会让我的类(class)变得如此肮脏和不纯粹!”但是当他们看到在这些场景中编写代码而不需要与导航纠缠在一起是多么容易之后,他们回来说“好吧,这是值得的!”

顺便说一句,如果您在企业类(class)中谈论我的 EF,我有一个完整的模块来处理这个问题......它被称为断开连接场景中的图表。 :)

关于c# - Entity Framework 和添加 POCO,而不添加子对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24293449/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com