复杂 Join/Query 与 OrmLite ServiceStack
Complex Join/Query with OrmLite ServiceStack
我在将 EF linq 示例转换为 OrmLite 时遇到问题。我已经确定了大部分查询,但一些深度连接或子查询正在解决一些问题。
这是我的 EF 查询:
var q = from orderProduct in orderProducts
join order in _erpContext.Orders.Include(x => x.BillingAddress.Country) on orderProduct.OrderId equals order.Id
join product in _erpContext.Products.Include(x => x.ProductCategories).Include(x => x.ProductManufacturers) on orderProduct.ProductId equals product.Id
where (storeId == 0 || storeId == order.StoreId) &&
(!startDate.HasValue || startDate.Value <= order.DateCreated) &&
(!endDate.HasValue || endDate.Value >= order.DateCreated) &&
(!orderStatusId.HasValue || orderStatusId == (int)order.OrderStatus) &&
(!orderTypeId.HasValue || orderTypeId == (int)order.OrderType) &&
(!paymentStatusId.HasValue || paymentStatusId == (int)order.PaymentStatus) &&
(!shippingStatusId.HasValue || shippingStatusId == (int)order.ShippingStatus) &&
(!order.Deleted) &&
(!product.Deleted) &&
(categoryId == 0 || product.ProductCategories.Count(pc => pc.CategoryId == categoryId) > 0) &&
(manufacturerId == 0 || product.ProductManufacturers.Count(pm => pm.ManufacturerId == manufacturerId) > 0) &&
(billingCountryId == 0 || order.BillingAddress.CountryId == billingCountryId);
如您所见,我在连接中使用了 Include() 函数。那是我卡住的部分。
这是我的 OrmLite 查询:
var q = _erpDbConnection.From<OrderProduct>()
.Join<Order>((x, y) => x.OrderId == y.Id)
.Join<Product>((x, y) => x.ProductId == y.Id)
.Where<OrderProduct>(x => x.ProductId != null && !x.Order.ContainsFreeMaterial && !x.Order.IsFitSizeOrder && x.Order.OrderType != OrderType.Stock)
.And<Order, Product>((o, p) => !o.Deleted && !p.Deleted);
if (storeId > 0)
{
q = q.And<Order>(x => x.StoreId == storeId);
}
if (billingCountryId > 0)
{
q = q.And<Order>(x => x.BillingAddress.CountryId == billingCountryId);
}
if (startDate.HasValue)
{
q = q.And<Order>(x => x.DateCreated <= startDate);
}
if (endDate.HasValue)
{
q = q.And<Order>(x => x.DateCreated >= endDate);
}
if (orderStatusId.HasValue)
{
q = q.And<Order>(x => (int) x.OrderStatus == orderStatusId);
}
if (orderTypeId.HasValue)
{
q = q.And<Order>(x => (int)x.OrderType == orderTypeId);
}
if (paymentStatusId.HasValue)
{
q = q.And<Order>(x => (int)x.PaymentStatus == paymentStatusId);
}
if (shippingStatusId.HasValue)
{
q = q.And<Order>(x => (int)x.ShippingStatus == shippingStatusId);
}
if (categoryId > 0)
{
q = q.And<Product>(x => x.ProductCategories.Any(y => y.CategoryId == categoryId));
}
if (manufacturerId > 0)
{
q = q.And<Product>(product => product.ProductManufacturers.Any(y => y.ManufacturerId == manufacturerId));
}
var filteredOrderProducts = _erpDbConnection.Select<OrderProduct>(q);
OrmLite 提供了类型化的 1:1 API 映射到正常 SQL,因此转换生成的 SQL 通常比 EF 查询更容易,后者通常不清楚查询是什么正在生成。
默认情况下 OrmLite SELECT 的来源 table 在这种情况下是 OrderProduct
:
var q = _erpDbConnection.From<OrderProduct>()
执行查询时返回的内容,即:
List<OrderProduct> results = db.Select(q);
要包含相关数据,您需要在源 OrderProduct
上定义 POCO References,然后可以使用 Load*
API 加载(深度 1 级) ,例如:
List<OrderProduct> results = db.LoadSelect(q);
您还可以使用 SelectMulti
一次 select 多个 table,例如:
var results = db.SelectMulti<OrderProduct, Order, Product>(q);
foreach (var tuple in results)
{
OrderProduct orderProduct = tuple.Item1;
Order order = tuple.Item2;
Product product = tuple.Item3;
}
对于任何其他自定义结果,您需要指定包含您想要 select 的结果的自定义 Select,例如:
q.Select<OrderProduct,Order,Product>((op,o,p) =>
new {
op, // all fields from OrderProduct table
o.Id,
p.Name,
etc...
});
但是您需要在包含与上述查询匹配的 public 属性的自定义架构中访问自定义结果集,例如:
var results = db.Select<OrderProductView>(q);
或使用 OrmLite's dynamic result set APIs 之一。
另请注意,您不能在 OrmLite 中进行嵌套查询,例如:
.Where<OrderProduct>(x => x.ProductId != null
&& !x.Order.ContainsFreeMaterial
&& !x.Order.IsFitSizeOrder
&& x.Order.OrderType != OrderType.Stock)
您需要查询 table 上的字段(就像您在正常 SQL 中所做的那样),您也可以在相同条件下查询多个 table:
.Where<OrderProduct,Order>((op,o) => ...);
我在将 EF linq 示例转换为 OrmLite 时遇到问题。我已经确定了大部分查询,但一些深度连接或子查询正在解决一些问题。
这是我的 EF 查询:
var q = from orderProduct in orderProducts
join order in _erpContext.Orders.Include(x => x.BillingAddress.Country) on orderProduct.OrderId equals order.Id
join product in _erpContext.Products.Include(x => x.ProductCategories).Include(x => x.ProductManufacturers) on orderProduct.ProductId equals product.Id
where (storeId == 0 || storeId == order.StoreId) &&
(!startDate.HasValue || startDate.Value <= order.DateCreated) &&
(!endDate.HasValue || endDate.Value >= order.DateCreated) &&
(!orderStatusId.HasValue || orderStatusId == (int)order.OrderStatus) &&
(!orderTypeId.HasValue || orderTypeId == (int)order.OrderType) &&
(!paymentStatusId.HasValue || paymentStatusId == (int)order.PaymentStatus) &&
(!shippingStatusId.HasValue || shippingStatusId == (int)order.ShippingStatus) &&
(!order.Deleted) &&
(!product.Deleted) &&
(categoryId == 0 || product.ProductCategories.Count(pc => pc.CategoryId == categoryId) > 0) &&
(manufacturerId == 0 || product.ProductManufacturers.Count(pm => pm.ManufacturerId == manufacturerId) > 0) &&
(billingCountryId == 0 || order.BillingAddress.CountryId == billingCountryId);
如您所见,我在连接中使用了 Include() 函数。那是我卡住的部分。
这是我的 OrmLite 查询:
var q = _erpDbConnection.From<OrderProduct>()
.Join<Order>((x, y) => x.OrderId == y.Id)
.Join<Product>((x, y) => x.ProductId == y.Id)
.Where<OrderProduct>(x => x.ProductId != null && !x.Order.ContainsFreeMaterial && !x.Order.IsFitSizeOrder && x.Order.OrderType != OrderType.Stock)
.And<Order, Product>((o, p) => !o.Deleted && !p.Deleted);
if (storeId > 0)
{
q = q.And<Order>(x => x.StoreId == storeId);
}
if (billingCountryId > 0)
{
q = q.And<Order>(x => x.BillingAddress.CountryId == billingCountryId);
}
if (startDate.HasValue)
{
q = q.And<Order>(x => x.DateCreated <= startDate);
}
if (endDate.HasValue)
{
q = q.And<Order>(x => x.DateCreated >= endDate);
}
if (orderStatusId.HasValue)
{
q = q.And<Order>(x => (int) x.OrderStatus == orderStatusId);
}
if (orderTypeId.HasValue)
{
q = q.And<Order>(x => (int)x.OrderType == orderTypeId);
}
if (paymentStatusId.HasValue)
{
q = q.And<Order>(x => (int)x.PaymentStatus == paymentStatusId);
}
if (shippingStatusId.HasValue)
{
q = q.And<Order>(x => (int)x.ShippingStatus == shippingStatusId);
}
if (categoryId > 0)
{
q = q.And<Product>(x => x.ProductCategories.Any(y => y.CategoryId == categoryId));
}
if (manufacturerId > 0)
{
q = q.And<Product>(product => product.ProductManufacturers.Any(y => y.ManufacturerId == manufacturerId));
}
var filteredOrderProducts = _erpDbConnection.Select<OrderProduct>(q);
OrmLite 提供了类型化的 1:1 API 映射到正常 SQL,因此转换生成的 SQL 通常比 EF 查询更容易,后者通常不清楚查询是什么正在生成。
默认情况下 OrmLite SELECT 的来源 table 在这种情况下是 OrderProduct
:
var q = _erpDbConnection.From<OrderProduct>()
执行查询时返回的内容,即:
List<OrderProduct> results = db.Select(q);
要包含相关数据,您需要在源 OrderProduct
上定义 POCO References,然后可以使用 Load*
API 加载(深度 1 级) ,例如:
List<OrderProduct> results = db.LoadSelect(q);
您还可以使用 SelectMulti
一次 select 多个 table,例如:
var results = db.SelectMulti<OrderProduct, Order, Product>(q);
foreach (var tuple in results)
{
OrderProduct orderProduct = tuple.Item1;
Order order = tuple.Item2;
Product product = tuple.Item3;
}
对于任何其他自定义结果,您需要指定包含您想要 select 的结果的自定义 Select,例如:
q.Select<OrderProduct,Order,Product>((op,o,p) =>
new {
op, // all fields from OrderProduct table
o.Id,
p.Name,
etc...
});
但是您需要在包含与上述查询匹配的 public 属性的自定义架构中访问自定义结果集,例如:
var results = db.Select<OrderProductView>(q);
或使用 OrmLite's dynamic result set APIs 之一。
另请注意,您不能在 OrmLite 中进行嵌套查询,例如:
.Where<OrderProduct>(x => x.ProductId != null
&& !x.Order.ContainsFreeMaterial
&& !x.Order.IsFitSizeOrder
&& x.Order.OrderType != OrderType.Stock)
您需要查询 table 上的字段(就像您在正常 SQL 中所做的那样),您也可以在相同条件下查询多个 table:
.Where<OrderProduct,Order>((op,o) => ...);