C# 在Linq中使用“选择”和“同时选择多个”
我正在尝试在以下查询中获取公司idC# 在Linq中使用“选择”和“同时选择多个”,c#,entity-framework,linq,C#,Entity Framework,Linq,我正在尝试在以下查询中获取公司id List<int> companyIds=new List<int> {4, 5, 6, 7}; var result = reservationRepository.Where(r => companyIds.Contains(r.CompanyId)) .SelectMany(t => t.Transactions) .Where(x => x
List<int> companyIds=new List<int> {4, 5, 6, 7};
var result = reservationRepository.Where(r => companyIds.Contains(r.CompanyId))
.SelectMany(t => t.Transactions)
.Where(x => x.DateCreated >= options.PaymentFromDate)
.Where(x => x.DateCreated < endDate)
.Select(x => new
{
Method = x.Method,
Amount = x.Amount,
VatAmount = x.VatAmount
});
我必须用Reservation表开始查询,因为我要从中获取相应的事务我无法更改模型。有什么方法可以通过查询同时获得交易详细信息和公司ID吗?您没有发布
GetAll()
或保留
和交易
类的代码,因此只能猜测
SelectMany
仅返回Transaction
对象。接下来的调用只查看事务
对象,而不查看预订
。如果Transaction
具有Reservation
属性,则可以使用x.Reservation.CompanyId
返回该值,例如:
.Select(x => new
{
CompanyID = x.Transaction.CompanyId,
Method = x.Method,
Amount = x.Amount,
VatAmount = x.VatAmount
});
在这种情况下,您甚至不应该从预订开始查询。最好查询交易
,例如:
var transactions = db.Transactions
.Where(x=>companyIds.Contains(x.Reservation.CompanyId) &&
x.DateCreated >= options.PaymentFromDate &&
x.DateCreated < endDate)
.Select(x => new
{
CompanyId = x.Reservation.Id
Method = x.Method,
Amount = x.Amount,
VatAmount = x.VatAmount
});
var transactions=db.transactions
.Where(x=>CompanyId.Contains(x.Reservation.CompanyId)&&
x、 DateCreated>=options.PaymentFromDate&&
x、 创建日期<结束日期)
.选择(x=>new
{
CompanyId=x.Reservation.Id
方法=x.方法,
金额=x.金额,
VatAmount=x.VatAmount
});
缺少预订属性
加上它。数据模型是为了方便查询,您显然需要这种关系
关系模型没有指定任何类型的图或层次结构,这是它相对于其他数据模型的主要优势。因为您需要事务,所以应该查询事务。在SQL中,只需添加一个JOIN
或WHERE In
子句,即可按事务和公司ID进行筛选
存储库反模式
这暴露了下一个更严重的问题。看起来您使用的是“通用”存储库反模式—一种低级别存储库接口,强加于更高级别的ORM(如EF Core)之上。这方面的问题是众所周知的,检查例如或从2009年
数据库集已经是一个存储库。DbContext已经实现了工作单元和断开连接的操作,并结合了多个实体存储库
贫血的存储库不需要隐藏数据访问细节,这就是ORM的用途。有意义的是一个专门的、多实体的存储库,为特定的用例服务,隐藏合并实体、验证检查、添加实现公共查询的方法的细节,用于所有涉及的实体
例如,这个专门的存储库可以有一个GetTransactionsByCompany(int)
方法,它可以封装整个查询并真正隐藏细节
对预订使用贫乏的存储库
会使更改查询变得更加困难,而不会带来任何好处。查询的详细信息仍然向调用方公开。您没有发布GetAll()
或保留
和事务
类的代码,因此只能猜测
SelectMany
仅返回Transaction
对象。接下来的调用只查看事务
对象,而不查看预订
。如果Transaction
具有Reservation
属性,则可以使用x.Reservation.CompanyId
返回该值,例如:
.Select(x => new
{
CompanyID = x.Transaction.CompanyId,
Method = x.Method,
Amount = x.Amount,
VatAmount = x.VatAmount
});
在这种情况下,您甚至不应该从预订开始查询。最好查询交易
,例如:
var transactions = db.Transactions
.Where(x=>companyIds.Contains(x.Reservation.CompanyId) &&
x.DateCreated >= options.PaymentFromDate &&
x.DateCreated < endDate)
.Select(x => new
{
CompanyId = x.Reservation.Id
Method = x.Method,
Amount = x.Amount,
VatAmount = x.VatAmount
});
var transactions=db.transactions
.Where(x=>CompanyId.Contains(x.Reservation.CompanyId)&&
x、 DateCreated>=options.PaymentFromDate&&
x、 创建日期<结束日期)
.选择(x=>new
{
CompanyId=x.Reservation.Id
方法=x.方法,
金额=x.金额,
VatAmount=x.VatAmount
});
缺少预订属性
加上它。数据模型是为了方便查询,您显然需要这种关系
关系模型没有指定任何类型的图或层次结构,这是它相对于其他数据模型的主要优势。因为您需要事务,所以应该查询事务。在SQL中,只需添加一个JOIN
或WHERE In
子句,即可按事务和公司ID进行筛选
存储库反模式
这暴露了下一个更严重的问题。看起来您使用的是“通用”存储库反模式—一种低级别存储库接口,强加于更高级别的ORM(如EF Core)之上。这方面的问题是众所周知的,检查例如或从2009年
数据库集已经是一个存储库。DbContext已经实现了工作单元和断开连接的操作,并结合了多个实体存储库
贫血的存储库不需要隐藏数据访问细节,这就是ORM的用途。有意义的是一个专门的、多实体的存储库,为特定的用例服务,隐藏合并实体、验证检查、添加实现公共查询的方法的细节,用于所有涉及的实体
例如,这个专门的存储库可以有一个GetTransactionsByCompany(int)
方法,它可以封装整个查询并真正隐藏细节
对预订使用贫乏的存储库
会使更改查询变得更加困难,而不会带来任何好处。查询的详细信息仍向呼叫者公开。至