2011-10-12 94 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(); 
}