2011-10-12 45 views
2

我有一个Team table和一个Player表以多对多的关系。有一个名为TeamOnPlayer的链接表。带POCO的EF为Team实体生成名为Person的导航属性,并生成导航。支柱。称为人民团体实体。将新记录插入LINQ的链接表到POCO的实体

我试图插入一个新的记录到TeamOnPlayer表中,但EF和POCO隐藏它。我试着这样做:

public static void AddPersonToTeam(int TeamId, int PersonId) 
    { 
     using (var ef = new korfballReportEntities()) 
     { 
      var team = GetTeam(TeamId); 
      var person = GetPerson(PersonId); 

      team.Person.Add(person); 
      person.Team.Add(team); 

      ef.SaveChanges(); 
     } 
    } 

的GetTeam(TeamId)和GetPerson(PERSONID)得到正确的团队和个人:

public static Team GetTeam(int id) 
    { 
     using (var ef = new korfballReportEntities()) 
     { 
      var q = from l in ef.Team 
        where l.Id == id 
        select l; 
      return q.Single(); 
     } 
    } 
public static Person GetPerson(int id) 
    { 
     using (var ef = new korfballReportEntities()) 
     { 
      var query = from p in ef.Person 
         where p.Id == id 
         select p; 
      return query.Single(); 
     } 
    } 

当它试图调用team.Person.Add(人)它会抛出一个异常:

“ObjectContext实例已被处置,不能再用于需要连接的操作。” System.Exception {System.ObjectDisposedException}

任何人都可以请给我看看正确的方法吗?

编辑

现在我明白了什么问题了,谢谢你。我对你包含的使用块有点困惑。例如这样的:

using (var ef = new korfballReportEntities()) 
{ 
//switch lazy loading off, only in this single context 
ef.Configuration.LazyLoadingEnabled = false; 

var repository = new MyRepository(ef); 
repository.AddPersonToTeam(int TeamId, int PersonId); 
} 

我应该在哪里放呢?

我做了别的事情。我只是做到了这一点,而且工作得很好。

public static void AddPersonToTeam(int TeamId, int PersonId) 
{ 
    using (var ef = new korfballReportEntities()) 
    { 
     var q = from t in ef.Team 
       where t.Id == TeamId 
       select t; 
     var team = q.Single(); 

     var q2 = from p in ef.Person 
       where p.Id == PersonId 
       select p; 
     var person = q2.Single(); 

     try 
     { 
      team.Person.Add(person); 
      person.Team.Add(team); 
     } 
     catch (Exception e) 
     { 
     } 

     ef.SaveChanges(); 
    } 
} 

唯一的问题是,我coludn't重用我GetPerson(INT ID)和GetTeam(INT ID)方法。

您认为如何?好吗?这是一个丑陋的方式?

+1

您可以包含GetTeam和GetPerson的代码吗? –

+0

当然可以。你可以在上面看到它。 – robessog

回答

0

我的猜测是您正在使用延迟加载 - 您的导航属性Team.PersonPerson.Team在您的实体类中被标记为virtual。结果是您的方法GetTeamGetPerson不会完全返回TeamPerson对象,而是从这些实体派生的动态创建的代理类的实例。这个动态代理支持延迟加载,这意味着当您第一次访问导航集合时,EF会尝试加载导航集合Team.PersonPerson.Team。当您在这些集合上调用Add时,会发生在您的AddPersonToTeam方法中。

现在的问题是代理是在您立即在GetTeamGetPerson方法中(在使用块的末尾)处理的上下文中创建的。代理已在内部存储对此上下文的引用,并将使用此上下文从数据库加载导航集合。

因为这些上下文已经处理,您会得到异常。

您应该重新设计您的代码:不要在存储库方法GetTeamGetPerson中创建新的上下文。您应该对所有操作使用相同的上下文:检索Team,检索Person并添加关系。例如:

public static void AddPersonToTeam(int TeamId, int PersonId) 
{ 
    using (var ef = new korfballReportEntities()) 
    { 
     var team = GetTeam(ef, TeamId); 
     var person = GetPerson(ef, PersonId); 

     team.Person.Add(person); 
     //person.Team.Add(team); <- not necessary, EF will handle this 

     ef.SaveChanges(); 
    } 
} 

public static Team GetTeam(korfballReportEntities ef, int id) 
{ 
    var q = from l in ef.Team 
      where l.Id == id 
      select l; 
    return q.Single(); 
} 

public static Person GetPerson(korfballReportEntities ef, int id) 
{ 
    var query = from p in ef.Person 
       where p.Id == id 
       select p; 
    return query.Single(); 
} 

另一种方法是使你的“资源库” /“服务”不是一成不变的,注入的背景下进入构造函数,然后使用整个存储库这一背景下。那么你不需要将上下文传递给每个方法。草图:

using (var ef = new korfballReportEntities()) 
{ 
    var repository = new MyRepository(ef); 
    repository.AddPersonToTeam(int TeamId, int PersonId); 
} 

public class MyRepository 
{ 
    private readonly korfballReportEntities _ef; 
    public MyRepository(korfballReportEntities ef) 
    { 
     _ef = ef; 
    } 

    public void AddPersonToTeam(int TeamId, int PersonId) 
    { 
     var team = GetTeam(TeamId); 
     var person = GetPerson(PersonId); 

     team.Person.Add(person); 

     _ef.SaveChanges(); 
    } 

    public Team GetTeam(int id) 
    { 
     var q = from l in _ef.Team 
       where l.Id == id 
       select l; 
     return q.Single(); 
    } 

    public Person GetPerson(int id) 
    { 
     var query = from p in _ef.Person 
        where p.Id == id 
        select p; 
     return query.Single(); 
    } 
} 

编辑有关性能优化

一个小东西:在这种特殊情况下延迟加载是没有必要的,更令人不安。它会导致加载一个(可能很长)的集合team.Person,当您只想向该集合添加一个额外的Person时。您可以关闭此特定操作的延迟加载(请参阅我的第二个示例):

using (var ef = new korfballReportEntities()) 
{ 
    //switch lazy loading off, only in this single context 
    ef.Configuration.LazyLoadingEnabled = false; 

    var repository = new MyRepository(ef); 
    repository.AddPersonToTeam(int TeamId, int PersonId); 
} 

public void AddPersonToTeam(int TeamId, int PersonId) 
{ 
    var team = GetTeam(TeamId); 
    var person = GetPerson(PersonId); 

    // if lazy loading is off, the collecton is null, so we must instantiate one 
    if (team.Person == null) 
     team.Person = new List<Person>(); 
    team.Person.Add(person); 

    _ef.SaveChanges(); 
} 
相关问题