gpt4 book ai didi

c# - Entity Framework 加载相关实体

转载 作者:行者123 更新时间:2023-11-30 15:28:33 27 4
gpt4 key购买 nike

我正在使用代码优先的 Entity Framework ,其基本上下文仅由标准 IDbSet 集合组成,其中 T 只是一个 POCO 类。在我的上下文中,我禁用了延迟加载。虽然我的模型类中有“导航属性”,但我已从中删除了 virtual 关键字。

存储库中的“全部获取”方法执行一些自定义过滤以确保当前用户只能看到他们拥有的数据,除非他们是管理员。我在以管理员身份登录时遇到了一个特殊问题,该问题也与某些记录相关联。由于我登录的实体已加载到上下文中,即使我已禁用延迟加载、虚拟删除并且未使用 Include 或 Load,结果中与我的配置文件关联的对象具有导航属性自动设置。

这不是我项目中的代码,只是一个展示我正在做的事情的例子。它可能有拼写错误和语法错误。

public class Record
{
public Guid Id { get; set; }
public string Name { get; set; }
public Owner Owner { get; set; } //No virtual keyword
public Guid OwnerId { get; set; }
}

public class Owner
{
public Guid Id { get; set; }
public string Name { get; set; }
public Collection<Record> Records { get; set; } //No virtual keyword
}

public class Context : DbContext
{
IDbSet<Owner> Owners { get; set; }
IDbSet<Record> Records { get; set; }
public static Context Create()
{
Context context = new Context();
context.Configuration.LazyLoadingEnabled = false; //Lazy loading disabled
return context;
}
}

public class Repository
{
private Context Context { get; set; }
public Owner CurrentOwner { get; private set; }
public Repository()
{
Context = Context.Create();

//Code here to get the application user and look up an associated "owner"
//entity if the user is an "owner" (they could just be an administrator)
//but the GetCurrentOwnerOrNull uses the Context to find the user
CurrentOwner = GetCurrentOwnerOrNull();
}

public IQueryable<Record> GetRecords(bool asAdmin)
{
IQueryable<Record> records = Context.Records; //Not including or loading Owner
if (asAdmin)
{
//Verify that the application user is an admin and throw exception otherwise
}
else
{
if (CurrentOwner == null)
{
//Throw a security exception
}
records = records.Where(r => r.OwnerId == CurrentOwner.Id);
}
return records;
}
}

再一次,上面的问题是,如果我以所有者身份运行该代码,无论是否是管理员,那么我拥有的那些记录将设置所有者属性而不是 null。我希望 Entity Framework 脱离我的业务,​​而不是自动设置它。它会导致下游出现问题,尤其是在以管理员和所有者身份运行代码时,因此您会返回一些 Owner = null 的记录,一些 Owner set。它很烦人。请帮我停下来。

最佳答案

这个错误实际上是一个功能。 Entity Framework 将自动在同一上下文中建立关联,即使实体是彼此独立加载的。

让我们假设如下:

public class Person
{
public Person()
{
this.Pets = new List<Pet>();
}

public int Id { get; set; }
public string Name { get; set; }

public virtual ICollection<Pet> Pets { get; set; }
}

public class Pet
{
public int Id { get; set; }
public string Name { get; set; }
public int PersonId { get; set; }

public virtual Person Owner { get; set; }
}

我们还假设这些与 DB-First 或与 Attributes/Fluent API code-first 正确关联。

数据库:

Persons
Id Name
1 Erik Philips

Pets
Id Name PersonId
1 Joe 1

这是将要发生的事情:

var pet = DbContext.Pets.FirstOrDefault(id => id == 1);
var person = DbContext.Persons.FirstOrDefault(id => id == 1);

Assert.AreEqual(person.Pets.Count(), 1);
Assert.IsNotNull(pet.Person);
Assert.AreEqual(pet.Person, person);

之所以会发生这种情况,是因为上下文将保留其缓存中的对象。如果你不关心持有这些对象的上下文,你将需要使用 AsNoTracking() .

关于c# - Entity Framework 加载相关实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25574175/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com