EF和Generic Repository,如何在更新时不添加新实体

时间:2012-12-19 17:20:14

标签: c# entity-framework entity-framework-5

尝试添加具有非新对象/实体图表的新实体时遇到问题。

这是我使用Code First方法的域类型:

public class Person : IEntity
{
   public int Id { get; set; }
   public string Name { get; set; }
   public List<PersonSession> Sessions { get; set; }
}

 public class PersonSession : IEntity
 {
    public int Id { get; set; }
    public Person Person { get; set; }
    public Session Session { get; set; }
 }

public class Session : IEntity
{
  public int Id { get; set; }
  public string Title { get; set; }     
}

所以我有一个人,他们可以有很多会议,并且会有一个他们的会议表。 Session表虽然没有任何对人的引用,但这就是PersonSessions表/关系的用途。

EF 5使用一个DbSet创建这3个表。

但是我试图用Generics制作一个简单的Repository模式,我有一个Save方法。

唯一的问题是,即使我使用Repository.GetAll()提供给我的现有会话,它也会向Sessions表添加一个新会话;

 public int Save(T t)
 {
    if (t.Id == 0)
       _context.Entry(t).State = EntityState.Added;
    else
       _context.Entry(t).State = EntityState.Modified;

    _context.SaveChanges();
    return t.Id;
 }

因此,当我创建2个新会话,然后通过Sessions的Generic Repo实例添加它们时,它们会被正确添加,

当我尝试创建一个新人并给他这样的现有会话时:

  private static void AddPerson()
  {

     var newPerson = new Person
                        {
                           JobTitle = EJobTitle.SoftwareDeveloper,
                           Name = "Mark W",
                        };

     var sessionsForPerson = new List<PersonSession>();

     var session1 = _sessionRepo.Retrieve(1);
     var session2 = _sessionRepo.Retrieve(2);

     sessionsForPerson.Add(new PersonSession
                              {
                                 Session = session1,
                                 Person = newPerson
                              });

     sessionsForPerson.Add(new PersonSession
                              {
                                 Session = session2,
                                 Person = newPerson,
                              });

     newPerson.Sessions = sessionsForPerson;

     _personRepo.Save(newPerson);
  }

它正在第二次添加会话。

我是否可以在PersonSession.Session属性上放置一个数据属性来告诉它这将始终是一个现有会话,还是需要在FluentApi中使用某些东西来指示EF?

感谢。

2 个答案:

答案 0 :(得分:1)

Save方法中,您将新Person的状态设置为EntityState.Added。执行此操作时,EF会将对象图中每个对象的状态设置为AddedSession已经有了Id&gt;这并不重要。这是除非图形中的对象先前由相同的上下文检索。在这种情况下,它们保持不变(只保存关联)。

这就是问题所在。您的存储库每个都有自己的上下文。这是通用存储库的常见问题。一种可能的补救措施是在存储库之外创建上下文并将其注入到一个业务事务中涉及的存储库中。另一个是通过在添加根实体后遍历对象图来确保现有对象以未修改状态进入上下文。

答案 1 :(得分:0)

尝试指定哪些属性是您的实体密钥:

public class Person : IEntity
{
    [Key]
    public int Id { get; set; }
    public string Name { get; set; }
    public List<PersonSession> Sessions { get; set; }
}

 public class PersonSession : IEntity
 {
    [Key]
    public int Id { get; set; }
    public Person Person { get; set; }
    public Session Session { get; set; }
 }

public class Session : IEntity
{ 
    [Key]
    public int Id { get; set; }
    public string Title { get; set; }     
}