我试图在以下查询中获得公司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.DateCreated >= options.PaymentFromDate)
.Where(x => x.DateCreated < endDate)
.Select(x => new
{
Method = x.Method,
Amount = x.Amount,
VatAmount = x.VatAmount
});
由于我使用select many
,我无法获得companyId
。请建议一种方法,将公司id连同结果一起返回。
预订表包含CompanyId。交易不包含公司Id
public class Reservation{
public int CompanyId { get; set; }
public virtual ICollection<Transaction> Transactions { get; set; }
}
public class Transaction{
public string Method{ get; set; }
public decimal Amount{ get; set; }
public decimal VatAmount{ get; set; }
}
我必须从Reservation表开始查询,因为我要从中获取相应的事务。我不能改变模型。我们是否可以通过查询同时获得交易细节和CompanyID ?
您没有发布GetAll()
或Reservation
和Transaction
类的代码,因此只能猜测。
SelectMany
只返回Transaction
对象。接下来的调用只看到Transaction
对象,看不到Reservation
。如果Transaction
具有Reservation
属性,则可以使用x.Reservation.CompanyId
返回该值,例如:
.Select(x => new
{
CompanyID = x.Transaction.CompanyId,
Method = x.Method,
Amount = x.Amount,
VatAmount = x.VatAmount
});
在这种情况下,您甚至不应该从Reservation
开始查询。最好查询Transactions
,例如:
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
});
缺失预约属性
添加它。数据模型旨在促进查询,显然您需要这种关系。
关系模型不指定任何类型的图或层次结构,这是它相对于其他数据模型的主要优点。由于需要事务,因此应该查询事务。在SQL中,您只需要添加JOIN
或WHERE IN
子句来根据Transaction和CompanyID进行过滤。
存储库反模式
这暴露了下一个更严重的问题。看起来你在使用"通用"库反模式——一个低层次的存储库接口,强加于像EF Core这样的高级ORM之上。这样做的问题是众所周知的,检查eg不需要存储库,实体框架核心或存储库的工作单元是2009年的新单例。
DbSet已经是一个存储库。DbContext已经实现了工作单元和断开连接的操作,组合了多个实体存储库。
没有必要用贫血的存储库来隐藏数据访问细节,这就是ORM的作用。有意义的是专门化的、多实体的存储库服务于特定的用例,隐藏组合实体的细节,验证检查,为所有涉及的实体添加实现公共查询的方法。这个专门的存储库可以有一个GetTransactionsByCompany(int)
方法,例如,它可以封装整个查询并真正隐藏细节。
为Reservations
使用贫血存储库使得更改查询更加困难,而没有提供任何好处。查询的详细信息仍然向调用者公开。
不做透明的类,最好使用查询语法,一切都是可用的。
var result =
from r in reservationRepository
where companyIds.Contains(r.CompanyId)
from t in t.Transactions
where t.DateCreated >= options.PaymentFromDate
&& t.DateCreated < endDate
select new
{
CompanyId = r.CompanyId,
Method = t.Method,
Amount = t.Amount,
VatAmount = t.VatAmount
};