我的商家模型名为Product
和Orders
,如下所示:
public class Product
{
public int ProductId {get; set;}
public string Name {get; set;}
}
public class Order
{
public int OrderId{get; set;}
public int ProductId {get; set;}
...
}
在我的存储库层中,我想返回一个产品集合,其中包含针对每个产品的订单数量,但我无法找出正确的方法或返回自定义结果集:
public ?? GetProductsWithOrderCount()
{
var resultSet = from p in Products
join o in Orders on p.ProductId equals o.ProductId into grp
select new
{
Product = p,
OrdersCount = grp.Count(); // Does not work, just for demonstration
};
return resultSet;
}
现在我知道我可以使用IEnumerable<object>
作为返回类型,但我必须将结果集转换为我在服务层中使用它的位置。
另一种选择是我可以创建另一个模型并返回IEnumerable<ProductWithOrderCount>
但是这会添加不代表我的系统的不必要模型:
public class ProductWithOrderCount
{
public Product Product {get; set;}
public int OrdersCount {get; set;}
}
还有其他办法吗?
答案 0 :(得分:1)
这就是DTO(数据传输对象)的用途,是的,完全合理地添加一个类来处理响应。您已经使用的类ProductWithOrderCount
很好,只有我会在类名的末尾添加DTO
以更清楚地表明这是一个用于存放自定义数据库结果的类。
答案 1 :(得分:1)
我的应用程序中有一个非常相似的要求。它是用于分页的,因为我的返回对象集合将类似于10,15或20个项目,但计数将是数百个内容的完整数据库计数。在您的情况下,似乎返回的数字和收集计数将是相同的。
我最终创建了一个通用的返回类型,它看起来像这样,但你可以随意调用类,如EnumerableWithCount
public class PagedList<T>
{
public int TotalCount { get; set; }
public IEnumerable<T> Items { get; set; }
public PagedList(IEnumerable<T> collection, int totalCount)
{
Items = collection;
TotalCount = totalCount;
}
}
如果我掌握了你正在寻找的东西,你会得到一个看起来像这样的返回类型。
IEnumerable<EnumerableWithCount<Product>>
答案 2 :(得分:1)
您的存储库层是隐藏所有存储抽象的层。不要让他们泄漏到您的业务逻辑中,即。业务代码不应该能够直接向存储发出其他查询,即使它看起来非常方便。同样适用于例外情况。如果您使用某种延迟加载,则存在在业务层中获取数据库级别异常或在演示文稿中更糟糕的风险。因此,您需要完全加载对象树并处理所有数据库/连接异常,或者将它们包装成StorageException之类的东西并将其抛弃。
如果您的业务逻辑需要ProductsWithOrders,那么就这样 - 您需要创建另一个类ProductsWithOrders。你可以想象并创建像Ledger这样的模板化课程,你可以像以后一样使用新的Ledger,但我会亲自等到你有另外一对课来证明它。
答案 3 :(得分:0)
from p in Products
select new ProductWithOrderCount()
{
Product = p,
OrdersCount = p.Orders.Count(),
};
删除联接并使用导航属性。
特殊的DTO课程是正确的方法。