gpt4 book ai didi

c# - 在 Entity Framework 和 Linq to Entities 中使用规范模式和表达式

转载 作者:行者123 更新时间:2023-11-30 12:55:35 25 4
gpt4 key购买 nike

我在通过 Entity Framework /Linq-to-Entities 访问数据库的存储库中有许多复杂的查询。通常,这些查询是由许多重要的子查询构成的。一般来说,子查询用于不同的存储库方法以及其他领域逻辑。它们在存储库层外部但可访问是有意义的。

因此我想使用规范模式来封装其中的一些子查询。

我正在为我的规范类使用一个基类:

public abstract class Specification<T> : ISpecification<T> where T : class
{
public abstract Expression<Func<T, bool>> ToExpression();

public virtual bool IsSatisfiedBy(T candidate)
{
var predicate = ToExpression().Compile();
return predicate(candidate);
}

public Specification<T> And(Specification<T> specification)
{
return new AndSpecification<T>(this, specification);
}

public Specification<T> Or(Specification<T> specification)
{
return new OrSpecification<T>(this, specification);
}
}

示例规范可能如下所示:

 public class IsAssignmentSetForStudentSpecification : Specification<Assignment>
{
private readonly Student _student;

public IsAssignmentSetForStudentSpecification(Student student)
{
_student = student;
}

public override Expression<Func<Assignment, bool>> ToExpression()
{
return x => !x.Exclusions.Contains(_student) &&
(
_student.Classes.Select(c => c.Subject).Intersect(x.Subjects).Any() ||
x.TutorGroups.Contains(_student.TutorGroup) ||
x.Houses.Contains(_student.House) ||
x.YearGroups.Contains(_student.YearGroup) ||
x.Students.Contains(_student)
);
}
}

如您所见,我不希望在每个存储库查询中编写此类代码。

作为存储库查询方法(使用各种规范)可能如下所示:

public ICollection<Assignment> GetAssignmentsDueInForStudent(Student student, DateRange dateRange)
{
var isAssignmentAssignedToStudent = new IsAssignmentSetForStudentSpecification(student);
var isAssignmentDueInDateRange = new IsAssignmentDueInDateRangeSpecification(dateRange);
var hasStudentCompletedAssignment = new HasStudentCompletedAssignmentSpecification(student);

return (from a in Set
.Where(x => isAssignmentAssignedToStudent
.And(isAssignmentDueInDateRange).IsSatisfiedBy(x))
.Where(x => !hasStudentCompletedAssignment.IsSatisfiedBy(x))
select a)
.ToList(queryOptions);
}

在上面的方法中,Set是一个 IDbSet<>

不幸的是,当我运行查询时,出现以下错误:

LINQ to Entities does not recognize the method 'Boolean IsSatisfiedBy(Beehive.Domain.Planner.Assignments.Assignment)' method, and this method cannot be translated into a store expression.

我该如何解决这个问题?

最佳答案

使用规范模式,您可以将域逻辑移出您的存储库。你可以有一个非常薄的存储库,看起来像:

public ICollection<Assignment> List(ISpecification<Assignment> specification)
{
return (from a in Set
.Where(specification.ToExpression())
select a)
.ToList(queryOptions);
}

然后,您可以在规范类中使用 And Or 和 Not 操作来组合规范,然后再将它们传入。

var isAssignmentDueForStudent = new isAssignmentSetForStudentSpecification(student)
.And(new IsAssignmentDueInDateRangeSpecification(dateRange))
.And(new HasStudentCompletedAssignmentSpecification(student).Not());

return assignmentRepository.List(isAssignmentDueForStudent);

这将逻辑排除在您的存储库之外,并且数据层不依赖于您的规范实现。此外,当您实现 AndSpecifications 等时,您将覆盖 ToExpression 以组合表达式,而不是 IsSatisfiedBy ,后者可能不需要是虚拟的。

关于c# - 在 Entity Framework 和 Linq to Entities 中使用规范模式和表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47508148/

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