C# 如何从每个对象禁用实体框架表引用(外部)列表?
我正在使用Sqlite数据库和System.Data.Sqlite 1.0.92 这里有两个表:C# 如何从每个对象禁用实体框架表引用(外部)列表?,c#,.net-4.0,entity-framework-5,system.data.sqlite,C#,.net 4.0,Entity Framework 5,System.data.sqlite,我正在使用Sqlite数据库和System.Data.Sqlite 1.0.92 这里有两个表: 桌上人: using (var ctx = new myEntities) { ctx.Configuration.ProxyCreationEnabled = false; ctx.Configuration.LazyLoadingEnabled = false; AllPersons= ctx.Persons.ToList(); AllStudents = ct
桌上人:
using (var ctx = new myEntities)
{
ctx.Configuration.ProxyCreationEnabled = false;
ctx.Configuration.LazyLoadingEnabled = false;
AllPersons= ctx.Persons.ToList();
AllStudents = ctx.Student.ToList();
}
拟人
人名
学生表:
using (var ctx = new myEntities)
{
ctx.Configuration.ProxyCreationEnabled = false;
ctx.Configuration.LazyLoadingEnabled = false;
AllPersons= ctx.Persons.ToList();
AllStudents = ctx.Student.ToList();
}
学生
PersonId(参考表Person FK)
学生号
现在,每次我在EF5中获取Persons集合时:
using (var ctx = new myEntities)
{
AllPersons = ctx.Persons.ToList();
}
还有hasAllPersons。学生的收集将包括在结果中
但我不需要它。当然,这只是一个例子,有很多大的表有这么多的引用,所以这里总是有性能问题
所以我尽量不让它影响我的成绩。所以我改变它:
using (var ctx = new myEntities)
{
ctx.Configuration.ProxyCreationEnabled = false;
ctx.Configuration.LazyLoadingEnabled = false;
AllPersons= ctx.Persons.ToList();
}
现在可以了,因为AllPersons.student
集合将始终为null
但现在我发现:如果我把人和学生聚在一起:
using (var ctx = new myEntities)
{
ctx.Configuration.ProxyCreationEnabled = false;
ctx.Configuration.LazyLoadingEnabled = false;
AllPersons= ctx.Persons.ToList();
AllStudents = ctx.Student.ToList();
}
现在参考文献仍然包括在
那么,在这种情况下,是否有必要在任何时候都不要让引用包含在中?
多谢各位
更新 对于一些朋友的请求,我解释我为什么需要它: 1:当我将它转换为json时,它将是一个死循环。即使我已经使用了Json.net
ReferenceLoopHandling
,Json的大小也非常大,会使服务器崩溃。(如果没有引用,它只是一个非常小的Json)
2:每次我获取客户端数据并需要保存时,它都会显示关于模型状态的异常,直到我将其设置为null
例如:
using (myEntities ctx = new myEntities())
{
ctx.Configuration.LazyLoadingEnabled = false;
ctx.Configuration.ProxyCreationEnabled = false;
Person model= ThisIsAModel();
model.students = null; // This is a key, I need set the students collection references to null , otherwise it will throw exception
ctx.Entry(model).State = EntityState.Modified;
ctx.SaveChanges();
}
3:这是一个更重要的问题。我已经获取了服务器上的所有数据和缓存。但它会让服务器启动时的加载时间很长。(因为数据和参考文献太多,这是主要问题),我不知道我会再次遇到什么样的问题
public List<Person> PersonsCache; // global cache
public List<Student> StudentsCache; // global cache
using (myEntities ctx = new myEntities())
{
ctx.Configuration.LazyLoadingEnabled = false;
ctx.Configuration.ProxyCreationEnabled = false;
// There is so many references and data, will let it very slow , when I first time get the all cache. even I only get the Person model, not other , just because some Collection has some references problem. It will very slow....
PersonsCache = ctx.Persons.ToList();
StudentsCache= ctx.Student.ToList();
}
公共列表PersonCache;//全局缓存
公开名单学生名单;//全局缓存
使用(myEntities ctx=new myEntities())
{
ctx.Configuration.LazyLoadingEnabled=false;
ctx.Configuration.ProxyCreationEnabled=false;
//有这么多的引用和数据,当我第一次获取所有缓存时,会让它非常慢。即使我只获取个人模型,而不是其他,只是因为某些集合存在一些引用问题。它会非常慢。。。。
PersonCache=ctx.Persons.ToList();
StudentsCache=ctx.Student.ToList();
}
它们在ObjectContext
中通过那里的EntityKey
自动链接。根据您想对您的人员
和学生
执行的操作,您可以将他们从对象上下文中分离出来
:
using (var ctx = new myEntities)
{
ctx.Configuration.ProxyCreationEnabled = false;
ctx.Configuration.LazyLoadingEnabled = false;
AllPersons= ctx.Persons.ToList();
foreach(var c in AllPersons)
{
ctx.Detach(c);
}
AllStudents = ctx.Student.ToList();
foreach(var c in AllStudents )
{
ctx.Detach(c);
}
}
如果实体是自动生成的,则将其复制粘贴到自己的代码中,并删除生成的关系,如子集合和外键。或者您不需要所有此类功能,可能是用户轻量级的框架,如,通常您的学生收藏不会从数据库中填充。当你到达酒店时,它就满了。此外,如果使用ToList()方法,实体框架将从数据中读取数据以填充集合
请检查这个。
明确选择要从数据库返回的内容。
使用。使用selectnew
子句,您可以创建匿名类型的新对象作为查询的结果,而不让引用包含在查询中。此语法允许您构造匿名数据结构。这些是在评估时创建的(惰性)。像这样:
using (var ctx = new myEntities())
{
var AllPersons = ctx.People.Select(c => new {c.PersonId, c.PersonName}).ToList();
}
即使您也不需要再禁用延迟加载
运行上面的查询后:
此查询当前使用selectnew{}
分配匿名类型,这要求您使用var
。如果要分配已知类型,请将其添加到select子句中:
private IEnumerable<MyClass> AllPersons;//global variable
using (var ctx = new myEntities())
{
AllPersons = ctx.People
.Select(c => new MyClass { PersonId = c.PersonId, PersonName = c.PersonName }).ToList();
}
在这种情况下,是否有任何时候都不让引用包括在内
解决这个问题的方法似乎很简单:不要映射关联。删除Student
集合。关于它,我没什么可说的。如果您使用的是4.5,请使用[IgnoreDataMember]
装饰任何属性+
听起来您正在尝试执行表继承,这是EF的另一个问题
如果我理解正确,你只是想确保你只得到你明确要求的东西,对吗
上面有一点提到过这一点,但要正确地执行此操作,您只需要选择一个匿名类型
var students = from s in _context.Students
select new{
StudentId,
StudentNo};
然后,当您想要更新此集合/对象时,我建议使用GraphDiff。GraphDiff确实有助于解决断开连接的实体和更新的问题()
因此,您的方法与此类似:
void UpdateStudent(Student student){
_context.UpdateGraph(student, map =>
map
.AssociatedEntity(c => c.Person));
_context.SaveChanges();
}
这样,您就可以更新对象上的任何属性,无论是否断开连接,并且不必担心关联
这是假设您正确映射了实体,老实说,我发现更容易将对象声明为属性,而不仅仅是ID,并使用映射文件正确映射它
因此:
班级人员{
int Id{get;set;}
字符串名称{get;set}
}
班级学生{
int Id{get;set;}
字符串StudentNo{get;set;}
Person{get;set;}
公共类StudentMap:EntityTypeConfiguration
{
公共学生地图()
{
//主键
HasKey(t=>t.Id);
//表和列映射
ToTable(“学生”);
属性(t=>t.Id);
//关系
HasRequired(t=>t.Person)
.HasForeignKey(d=>d.PersonId);
}
}
希望这是有意义的。您不需要创建视图模型,但肯定可以。这种方法确实可以更轻松地将断开连接的项目映射回数据库。问题所在
正如您所说,当您同时加载父对象和子对象时
var db = new YourDbContext();
db.Configuration.LazyLoadingEnabled = false;
var parentList= db.YourParentSet.ToList();
var childList= db.YourChildSet.ToList();
var db1 = new YourDbContext();
db1.Configuration.LazyLoadingEnabled = false;
var parentList= db.YourParentSet.ToList();
var db2 = new YourDbContext();
db2.Configuration.LazyLoadingEnabled = false;
var childList= db.YourChildSet.ToList();
var db1 = new YourDbContext();
db1.Configuration.LazyLoadingEnabled = false;
var parentList= db.YourParentSet
.Select(x=>new /*Model()*/{
Property1=x.Property1,
Property2=x.Property2, ...
}).ToList();
public List<Person> PersonsCache;
public List<Student> StudentsCache;
using (myEntities ctx = new myEntities())
{
ctx.Configuration.ProxyCreationEnabled = false;
PersonsCache = ctx.Persons
.AsNoTracking()
.ToList();
}
using (myEntities ctx = new myEntities())
{
ctx.Configuration.ProxyCreationEnabled = false;
StudentsCache= ctx.Student
.AsNoTracking()
.ToList();
}
using (var ctx = new myEntities)
{
AllPersons = ctx.Persons.ToList();
}