在一个规范中结合c#代码和数据库代码
本文关键字:代码 结合 数据库 范中 一个 | 更新日期: 2023-09-27 18:06:38
有时您需要定义一些业务规则,Specification模式就是一个有用的工具。例如:
public class CanBorrowBooksSpec : ISpecification<Customer>
{
public bool Satisfies(Customer customer)
{
return customer.HasLibraryCard
&& !customer.UnpaidFines.Any();
}
}
然而,我经常发现我需要将这些规则"推"到SQL中以提高性能或迎合诸如页面记录列表之类的事情。
然后我必须为规则编写两次代码,一次用CLR代码,一次用SQL(或ORM语言)。
你是如何组织这样的代码的?
似乎最好将代码保存在同一个类中。这样,如果开发人员正在更新业务规则,他们忘记更新两组代码的机会就会减少。例如:
public class CanBorrowBooksSpec : ISpecification<Customer>
{
public bool Satisfies(Customer customer)
{
return customer.HasLibraryCard
&& !customer.UnpaidFines.Any();
}
public void AddSql(StringBuilder sql)
{
sql.Append(@"customer.HasLibraryCard
AND NOT EXISTS (SELECT Id FROM CustomerUnpaidFines WHERE CustomerId = customer.Id)");
}
}
然而,这对我来说似乎很丑陋,因为我们现在把关注点混合在一起了。
另一种选择是使用LINQ - to - yourorm解决方案,因为LINQ代码可以针对集合运行,或者可以将其转换为SQL。但我发现,除了在最琐碎的场景中,这种解决方案很少是可行的。
你是做什么的?
我们使用实体框架的规范模式。这是我们如何处理它的
public interface ISpecification<TEntity>
{
Expression<Func<TEntity, bool>> Predicate { get; }
}
public class CanBorrowBooksSpec : ISpecification<Customer>
{
Expression<Func<Customer, bool>> Predicate
{
get{ return customer => customer.HasLibraryCard
&& !customer.UnpaidFines.Any()}
}
}
然后你可以对LINQ-to-Entities使用它,比如
db.Customers.Where(canBorrowBooksSpec.Predicate);
在LINQ-to-Objects中,如
customerCollection.Where(canBorrowBooksSpec.Predicate.Compile());