我想创建一个如下所示的视图模型,其中CustomerInfo
是包含订单集合的视图模型,每个订单都包含订单明细的集合。
public class CustomerInfo
{
public CustomerInfo()
{
OrderInfo = new HashSet<OrderInfo>();
}
public int Custid { get; set; }
public string City { get; set; }
public string Region { get; set; }
public virtual ICollection<OrderInfo> OrderInfo { get; set; }
}
public class OrderInfo
{
public OrderInfo()
{
OrderDetails = new HashSet<OrdDetails>():
}
public int OrderId { get; set; }
public DateTime OrderDate { get; set; }
public ICollection<OrdDetails> OrderDetails { get; set; }
}
public class OrdDetails
{
public int Orderid { get; set; }
public int Productid { get; set; }
public decimal Unitprice { get; set; }
public short Qty { get; set; }
public decimal Discount { get; set; }
public virtual OrderInfo Order { get; set; }
}
SQL Server数据库包含一个视图,该视图使用联接存储来自三个相关表:customer
,order
和orderdetails
的数据。
我是否可以使用无键实体类型或DBQuery将T-SQL视图映射到CustomerInfo
视图模型类?
如果可能,我宁愿不使用DBQuery,因为最新的.NET Core版本不再支持DBQuery,并且如果我们决定升级,我不希望该应用程序损坏。
这不是一件容易的事。
假设有一个实体类,声明为数据库记录包含复合Customer
,Order
和OrdDetail
关系主列,
public partial class CustomerOrderDetail_Entity : ICustomerInfo, IOrderInfo, IOrdDetails
{
public int Custid { get; set; }
public string City { get; set; }
public string Region { get; set; }
public int OrderId { get; set; }
public DateTime OrderDate { get; set; }
public int Orderid { get; set; }
public int Productid { get; set; }
public decimal Unitprice { get; set; }
public short Qty { get; set; }
public decimal Discount { get; set; }
}
为了使开始时变得容易和简单,请尝试创建视图并查询这三个表中的每一列,
SELECT
dbo.Customer.Custid, dbo.Customer.City, dbo.Customer.Region,
dbo.[Order].OrderId, dbo.[Order].OrderDate,
dbo.OrdDetail.Productid, dbo.OrdDetail.Qty, dbo.OrdDetail.Discount, dbo.OrdDetail.Unitprice
FROM dbo.Customer LEFT OUTER JOIN
dbo.[Order] ON dbo.Customer.Custid = dbo.[Order].Custid LEFT OUTER JOIN
dbo.OrdDetail ON dbo.[Order].OrderId = dbo.OrdDetail.Orderid
然后,创建数据访问,ORM功能来满足您的需求,
virtual CustomerInfo GetCustomerOrderDetail(int custId, string connectionStringName = null)
{
IEnumerable<CustomerOrderDetail_Entity> entities;
using (var conn = DbConnectionFactory.CreateDbConnection(connectionStringName ?? DefaultConnectionName))
{
conn.Open();
entities = conn.Query<CustomerOrderDetail_Entity>(@"
SELECT *
FROM uv_CustomerOrderDetails
where CustId = @CustId
", new { CustId = custId });
}
return entities?.ConvertTo<CustomerInfo>();
}
无论您的数据结构多么复杂,它都是ORM映射的东西。由于现在所有事物都在内存中,因此使用OrdDetails
将它们转换或映射为OrderInfo
,CustomerInfo
和legacy for-loop, LINQ, or 3rd-party mapper package
类可能并不困难。
但是,不应为一般目的而创建第一个视图,对于不经常调用的查询,例如数据分析,这是更好的选择,否则它会不断浪费大量流量来检索带有冗余列的较大数据集,例如[ C0],Customer.City
,对于客户而言,它们都是相同的,对于相同的订单,它们也都是Customer.Region
。
[像这样,比伯爵眼镜还相对优化的视图,
数据不再完全填充。相反,需要许多支持方法来使其完成。这是一个示例,我如何使用第二个视图,然后将数据集分别转换为[Order].OrderDate
尽管现在节省了大量数据,但CustomerOrderDetail_Entity
SELECT
dbo.Customer.Custid,
dbo.[Order].OrderId,
dbo.OrdDetail.Productid
FROM dbo.Customer LEFT OUTER JOIN
dbo.[Order] ON dbo.Customer.Custid = dbo.[Order].Custid LEFT OUTER JOIN
dbo.OrdDetail ON dbo.[Order].OrderId = dbo.OrdDetail.Orderid
,CustomerInfo
和OrderInfo
。OrdDetails
坦率地说,随着系统复杂性的增加,还有很多事情要做。除非您的系统保持如此小,我的意见是
virtual CustomerInfo GetCustomerOrderDetail(int custId, string connectionStringName = null) { var customerInfo = DBHelper.CachedCustomerInfo(custId); var orders = entities ?.Where(o => o.Custid == custId) ?.GroupBy(o => o.Custid) ?.SelectMany(group => group); if (orders?.Count() > 0 != true) { return customerInfo; } customerInfo.OrderInfo = new List<OrderInfo>(); // fill orders foreach (var order in orders) { var orderId = order.OrderId; if (orderId <= 0) { continue; } var orderInfo = DBHelper.CachedOrderInfo(orderId); customerInfo.OrderInfo.Add(orderInfo); // fill order details var orderDetails = DBHelper.CachedOrderDetails(orderId); if (orderDetails?.Count() > 0 != true) { continue; } orderInfo.OrderDetails = orderDetails.LinkOrder(orderInfo).ToList(); } return customerInfo; } // query CustomerInfo by PK:CustId, and Cache CRUD virtual CustomerInfo CachedCustomerInfo(int custId); // query OrderInfo by PK:OrderId, and Cache CRUD virtual OrderInfo CachedOrderInfo(int orderId); // query OrdDetails list by FK:OrderId, and Cache CRUD virtual IEnumerable<OrdDetails> CachedOrderDetails(int orderId); // make OrdDetails.Order property link to its owner Order virtual IEnumerable<OrdDetails> LinkOrder(this IEnumerable<OrdDetails> details, OrderInfo order);
。