我有很多关系的Team表和Player表。有一个名为TeamOnPlayer的链接表。带有POCO的EF为团队实体生成名为Person的导航属性,并生成导航。支柱。称为Team for the People实体。
我正在尝试在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(person)时会抛出异常:
“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();
}
}
唯一的问题是,我不能重用我的GetPerson(int id)和GetTeam(int id)方法。
你怎么看?好吗?这是一种丑陋的方式吗?答案 0 :(得分:0)
我的猜测是您正在使用延迟加载 - 导航属性Team.Person
和Person.Team
在您的实体类中标记为virtual
。结果是您的方法GetTeam
和GetPerson
并不完全返回Team
和Person
个对象,而是从这些实体派生的动态创建的代理类的实例。此动态代理支持延迟加载,这意味着当您第一次访问导航集时,EF会尝试加载导航集Team.Person
和Person.Team
。当您在这些集合上调用AddPersonToTeam
时,会在Add
方法中发生这种情况。
现在的问题是代理是在一个上下文中创建的,您可以立即在GetTeam
和GetPerson
方法(在使用块的末尾)中进行处理。代理在内部存储了对此上下文的引用,并将使用此上下文从数据库加载导航集合。
因为这些情境已被处理,所以你会得到例外。
您应该重新设计一下代码:不要在存储库方法GetTeam
和GetPerson
中创建新的上下文。您应该为所有操作使用相同的上下文:检索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();
}