【发布时间】:2018-04-11 22:34:44
【问题描述】:
我在我的项目中使用了一个通用的存储库类,所以一个实际的具体存储库是通过依赖注入来实例化的:
services.AddTransient<IRepository<Passenger>, EntityFrameworkRepository<Passenger>>();
下面是通用存储库本身,请注意我正在使用规范模式进行查询过滤。规范本身只返回一个Expression<TEntity, bool> 表达式对象。
public class EntityFrameworkRepository<TEntity> : IRepository<TEntity>
where TEntity : class
{
public async Task<IEnumerable<TEntity>> Find(Specification<TEntity> specification)
{
return await _context.Set<TEntity>()
.Where(specification.ToExpression())
.AsNoTracking()
.ToListAsync();;
}
public async Task<TEntity> FindOne(Specification<TEntity> specification)
{
return await _context.Set<TEntity>()
.AsNoTracking()
.FirstOrDefaultAsync(specification.ToExpression());
}
public async Task<TEntity> GetById(object id)
{
return await _context.Set<TEntity>().FindAsync(id);
}
}
仅返回确认电子邮件地址的乘客的规范的实现:
public class PermanentPassengerSpecification : Specification<Passenger>
{
public override Expression<Func<Passenger, bool>> ToExpression()
{
return passenger => passenger.EmailConfirmed == true;
}
}
另一个通过电话号码匹配乘客
public class PassengerByPhoneSpecification : Specification<Passenger>
{
private readonly PhoneNumber _phoneNumber;
public PassengerByPhoneSpecification(PhoneNumber phoneNumber)
{
if (phoneNumber == null)
throw new ArgumentNullException();
_phoneNumber = phoneNumber;
}
public override Expression<Func<Passenger, bool>> ToExpression()
{
return passenger => passenger.PhoneNumber == _phoneNumber;
}
}
所以,基本上当我使用 FindOne 方法从存储库中查询数据时,EF Core 会抛出这个:
InvalidOperationException: The EF.Property<T> method may only be used within LINQ queries.
Microsoft.EntityFrameworkCore.EF.Property<TProperty>(object entity, string propertyName)
lambda_method(Closure , TransparentIdentifier<Passenger, PhoneNumber> )
System.Linq.AsyncEnumerable+WhereSelectEnumerableAsyncIterator+<MoveNextCore>d__8.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.ConfiguredTaskAwaitable+ConfiguredTaskAwaiter.GetResult()
System.Linq.AsyncEnumerable+AsyncIterator+<MoveNext>d__10.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.ConfiguredTaskAwaitable+ConfiguredTaskAwaiter.GetResult()
System.Linq.AsyncEnumerable+<FirstOrDefault_>d__165.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
Microsoft.EntityFrameworkCore.Query.Internal.AsyncLinqOperatorProvider+TaskResultAsyncEnumerable+Enumerator+<MoveNext>d__3.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
Microsoft.EntityFrameworkCore.Query.Internal.AsyncLinqOperatorProvider+ExceptionInterceptor+EnumeratorExceptionInterceptor+<MoveNext>d__5.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler+<ExecuteSingletonAsyncQuery>d__23.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
Taksapp.Infrastructure.Repositories.EntityFrameworkRepository+<FindOne>d__3.MoveNext() in EntityFrameworkRepository.cs
有什么方法可以解决这个问题吗?
【问题讨论】:
-
什么是
Specification<TEntity>?生成的任何表达式都不符合 EF 的预期 -
这没有意义,因为这些规范只包含与数据库实体相关的表达式。 @Nkosi
-
显示使用示例
-
完成!!我用一个例子编辑了这篇文章
-
显示导致该特定错误的那个。堆栈跟踪有
<Passenger, PhoneNumber>。我正在尝试缩小错误的真实情况
标签: c# asp.net-core entity-framework-core