我是EF核心的新手。我有一个具有常规属性(名称,地址,电子邮件)的客户模型。
我需要一个属性来为客户计算当前余额。
这将是一个非常密集的计算(一旦存储了许多记录),因此我认为应该将其存储在Method中而不是在计算出的属性中正确吗?
我假设我需要添加诸如.GetCurrentBalance()的方法。
我将把这种方法放在哪里?
下面的简化代码:
我的客户模型
public class Customer
{
public int CustomerId { get; set; }
public string Name { get; set; }
public string EmailAddress { get; set; }
public virtual IEnumerable<SalesInvoice> SalesInvoices{ get; set; }
}
我的销售发票模型
public class SalesInvoice
{
public int SalesInvoiceId { get; set; }
public int CustomerId { get; set; }
public virtual IEnumerable<SalesInvoiceDetail> SalesInvoiceDetails{ get; set; }
}
我的销售发票明细模型
public class SalesInvoiceDetail
{
public int SalesInvoiceDetailId { get; set; }
public int Qty { get; set; }
public decimal UnitPrice { get; set; }
}
创建返回所需结果的辅助方法。一切都应该围绕IQueryable展开:
public class CustomerIdWithBalance
{
public int CustomerId { get; set; }
public decimal Balance { get; set; }
}
public class CustomerWithBalance
{
public Customer Customer { get; set; }
public decimal Balance { get; set; }
}
public static class BusinessLogicExtensions
{
public static IQueryable<CustomerIdWithBalance> GetCustomerIdAndBalance(this IQueryable<Customer> customers)
{
var grouped =
from c in customers
from si in c.SalesInvoices
from sid in si.SalesInvoiceDetails
group sid by new { c.CustomerId } into g
select new CustomerIdWithBalance
{
g.Key.CustomerId,
Balance = x.Sum(x => x.Qty * x.UnitPrice)
}
return grouped;
}
public static IQueryable<CustomerWithBalance> GetCustomerAndBalance(this IQueryable<CustomerIdWithBalance> customerBalances, IQueryable<Customer> customers)
{
var query =
from b in customerBalances
join c in customers on b.CustomerId equals c.CustomerId
select new CustomerWithBalance
{
Customer = c,
Balance = b.Balance
};
return query;
}
}
稍后,当您需要通过API调用返回该信息时(假设的示例)
var qustomerIdsWithHighBalance =
from c in ctx.Customers.GetCustomerIdAndBalance()
where c.Balance > 1000
select c.CustomerId;
var qustomersWithHighBalance =
ctx.Customers.GetCustomerIdAndBalance()
.Where(c => c.Balance > 1000)
.GetCustomerAndBalance(ctx.Customers);
var customersByMatchAndPagination = ctx.Customers
.Where(c => c.Name.StartsWith("John"))
.OrderBy(c => c.Name)
.Skip(100)
.Take(50)
.GetCustomerAndBalance(ctx.Customers);
您将获得所需的结果,而无需其他数据库往返。使用属性,您可能会将太多数据加载到内存中。
有关使用EF及其局限性的一切。但是,由于EF团队忙于创建绩效有效的事物,世界并未停止。
让我们安装https://github.com/axelheer/nein-linq
并围绕创建扩展方法 Customer
public static class CustomerExtensions
{
[InjectLambda]
public static TotalBalance(this Customer customer)
=> throw new NotImplmentedException();
static Expression<Func<Customer, decimal>> TotalBalance()
{
return customer =>
(from si in customer.SalesInvoices
from sid in si.SalesInvoiceDetails
select sid)
.Sum(x => x.Qty * x.UnitPrice));
}
}
一切变得方便:
var customersWithHighBalance =
from c in ctx.Customers.ToInjectable()
where c.TotalBalance() > 1000
select c;
var customersWithHighBalance =
from c in ctx.Customers.ToInjectable()
let balance = c.TotalBalance()
where balance = balance > 1000
select new CustomerWithBalance
{
Customer = c,
Balance = balance
};
var customersWithBalance =
from c in ctx.Customers.ToInjectable()
where c.Name.StartsWith("John")
select new CustomerWithBalance
{
Customer = c,
Balance = c.TotalBalance()
};
var paginated =
.OrderBy(c => c.Name)
.Skip(100)
.Take(50);
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句