使用带有 AsEnumerable 的 EF 的构造函数投影到域 class
Projecting to domain class with constructor with EF with AsEnumerable
TL;DR
AsEnumerable()
在 IQueryable()
上使用是否更安全(例如,它是否已经作为 ToList()
执行)以获得错误 [=17 的解决方法(见下文) =]?
换句话说,在 IQueryable()
上使用 AsEnumerable()
有什么影响,尤其是在将 Where()
链接到它时。
请阅读下面的完整上下文和信息。
长版
我正在为我的存储库层实现一个抽象,因为我必须能够从 JSON 文件、XML 文件以及 EntityFramework(数据库)中读取数据。
问题描述
我在投影我的 EF 实体时遇到错误 automapper Only parameterless constructors and initializers are supported in LINQ to Entities.
执行如下代码时:
public IEnumerable<Person> All() {
return _dataContext
.People
.Select(p => new Person(p.Id, p.FirstName, p.LastName));
}
作为参考,这是我的DbContext
,所以你看到上面的_dataContext.People
returns一个IQueryable<EFPerson>
:
public class EFDataContext : DbContext
{
public IDbSet<EFPerson> People { get; set; }
public EFDataContext()
: this(Settings.Default.EFDataContextConnectionString) { }
public EFDataContext(string nameOrConnectionString)
: this(() => nameOrConnectionString) { }
public EFDataContext(Func<string> connectionStringProvider)
: base(connectionStringProvider()) { }
protected override void OnModelCreating(DbModelBuilder modelBuilder) {
modelBuilder.Entity<EFPerson>()
.HasKey(p => p.Id)
.ToTable(Settings.Default.PeopleTable);
}
}
我的解决方案
我不想使用 AutoMapper
,我也不想让我的域实体具有 setters
- 因为它们需要 immutable/read-only 用于业务模型我在写。
我想出的解决方案是使用 .AsEnumerable()
,然后使用我的域实体的构造函数进行投影:
public IEnumerable<Person> All() {
return _dataContext
.People
.AsEnumerable()
.Select(p => new Person(p.Id, p.FirstName, p.LastName));
}
代码运行速度很快,之后我还可以在域实体上进行 .Where
投影。 我认为这是安全的,因为我的理解是 .AsEnumerable
不会像 .ToList
那样立即评估。
问题回顾
我的问题 这样,我的假设是否正确。这样做是安全的解决方法,还是我应该以不同的方式建模 - 使用 AutoMapper 或在我的 EntityFramework 服务层/存储库实现中编写更长的逻辑?
由于你的问题很广泛,我将描述我的解决方案:
在 Entity Framework:
中使用您的域实体
public class EFDataContext : DbContext
{
public IDbSet<Person> People { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder) {
modelBuilder.Entity<Person>()
.HasKey(p => p.Id)
.ToTable(Settings.Default.PeopleTable);
}
}
根据需要设计您的实体:
public class Person
{
private Person() //for EF
{
}
public Person(string name) //for me
{
Name = name;
}
public int Id { get; private set; }
public string Name { get; private set; }
public string LastName { get; private set; }
}
查询:
public IEnumerable<Person> All() {
return _dataContext
.People
.AsEnumerable();
}
为什么我在这里使用AsEnumerable
?只是为了隐藏我的数据库,它是 IQueryable
。
如您所见,EF 允许使用域对象。
TL;DR
AsEnumerable()
在 IQueryable()
上使用是否更安全(例如,它是否已经作为 ToList()
执行)以获得错误 [=17 的解决方法(见下文) =]?
换句话说,在 IQueryable()
上使用 AsEnumerable()
有什么影响,尤其是在将 Where()
链接到它时。
请阅读下面的完整上下文和信息。
长版
我正在为我的存储库层实现一个抽象,因为我必须能够从 JSON 文件、XML 文件以及 EntityFramework(数据库)中读取数据。
问题描述
我在投影我的 EF 实体时遇到错误 automapper Only parameterless constructors and initializers are supported in LINQ to Entities.
执行如下代码时:
public IEnumerable<Person> All() {
return _dataContext
.People
.Select(p => new Person(p.Id, p.FirstName, p.LastName));
}
作为参考,这是我的DbContext
,所以你看到上面的_dataContext.People
returns一个IQueryable<EFPerson>
:
public class EFDataContext : DbContext
{
public IDbSet<EFPerson> People { get; set; }
public EFDataContext()
: this(Settings.Default.EFDataContextConnectionString) { }
public EFDataContext(string nameOrConnectionString)
: this(() => nameOrConnectionString) { }
public EFDataContext(Func<string> connectionStringProvider)
: base(connectionStringProvider()) { }
protected override void OnModelCreating(DbModelBuilder modelBuilder) {
modelBuilder.Entity<EFPerson>()
.HasKey(p => p.Id)
.ToTable(Settings.Default.PeopleTable);
}
}
我的解决方案
我不想使用 AutoMapper
,我也不想让我的域实体具有 setters
- 因为它们需要 immutable/read-only 用于业务模型我在写。
我想出的解决方案是使用 .AsEnumerable()
,然后使用我的域实体的构造函数进行投影:
public IEnumerable<Person> All() {
return _dataContext
.People
.AsEnumerable()
.Select(p => new Person(p.Id, p.FirstName, p.LastName));
}
代码运行速度很快,之后我还可以在域实体上进行 .Where
投影。 我认为这是安全的,因为我的理解是 .AsEnumerable
不会像 .ToList
那样立即评估。
问题回顾
我的问题 这样,我的假设是否正确。这样做是安全的解决方法,还是我应该以不同的方式建模 - 使用 AutoMapper 或在我的 EntityFramework 服务层/存储库实现中编写更长的逻辑?
由于你的问题很广泛,我将描述我的解决方案: 在 Entity Framework:
中使用您的域实体public class EFDataContext : DbContext
{
public IDbSet<Person> People { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder) {
modelBuilder.Entity<Person>()
.HasKey(p => p.Id)
.ToTable(Settings.Default.PeopleTable);
}
}
根据需要设计您的实体:
public class Person
{
private Person() //for EF
{
}
public Person(string name) //for me
{
Name = name;
}
public int Id { get; private set; }
public string Name { get; private set; }
public string LastName { get; private set; }
}
查询:
public IEnumerable<Person> All() {
return _dataContext
.People
.AsEnumerable();
}
为什么我在这里使用AsEnumerable
?只是为了隐藏我的数据库,它是 IQueryable
。
如您所见,EF 允许使用域对象。