插入具有关联的实体会导致重复关联

时间:2013-11-23 18:08:19

标签: c# sql entity-framework

当我尝试将一个实体插入到数据库中时,该实体与已经在数据库中的另一个实体有关联,并且具有实体框架的id,关联实体也会被插入。这会导致关联实体的重复条目。

在Repository类中插入方法

public T Insert(T entity)
{
   DbSet.Add(entity);
   Context.SaveChanges();
   return entity;
}

调用插入方法

这发生在我的代码中的某处。我把它保存到我的会话变量中。

using(var repository  = new Repository<User>())
{
    user = repository.GetById(id);
}

然后是其他地方:

Post post = new Post{ User = user, Content ="oO" };

using (var rep = new Repository<Post>())
{
    rep.Insert(post);
}

我使用下面的代码段解决了重复的插入内容。这有一个更好的方法,而不是为每个实体类型强制转换并重新连接相关的entites?

if (entity is Post)
{
     Post post = (Post)(object)entity;
     Context.Users.Attach(post.User);

}

2 个答案:

答案 0 :(得分:0)

您的存储库很可能会创建上下文的新实例,而不是共享一个。这就是Post存储库中新创建的上下文不“看到”用户对象实例的原因。

通过控制上下文的生命周期并将同一实例注入同一工作单元中的不同存储库来正确解决此问题。

编辑:基于容器的注入可以为您提供很多帮助,但首先要将数据上下文作为存储库所需的构造函数参数。然后,想想你的背景的生命周期。

在Web应用程序中,请求生存期通常最方便。在WPF应用程序中,您可能具有视图模型生存期,每个视图模型中的新上下文。

容器是否满足依赖性是另一回事。

答案 1 :(得分:0)

这些通用存储库已经发布。有许多理由不使用它们。这是其中之一。存储库表明你遵守单一责任原则,但他们没有遵守。它们包含“特洛伊木马”DbContext,这是一个比通用存储库应该具有更多责任的组件。因此,当存储库保存其“自己的”实体时,任何旧时刻它都会通过保存其他实体而脱节。

通过抛弃这个无用的层,让你的生活更轻松。 DbSet是一个存储库,DbContext是一个工作单元。 (我这里只quoting。在EF体系结构中,UoW包含存储库,这些存储库没有保存责任! UoW有。

删除这些通用存储库,您只需执行

即可
using(var db = new MyContext())
{
    var user = db.Users.Find(id);
    Post post = new Post{ User = user, Content ="oO" };
    db.Posts.Add(post); // User is not added because it is known to the context.
    db.SaveChanges();
}

这是一种保存连接到用户的帖子的专用方法。试图为此制定一些通用方法是没有意义的,因为它是一个特定的任务(或用例)。正如您已经注意到的那样,在尝试概括此类任务时,您可能无法检查对象并引入丑陋且笨重的ifswitch链。