【问题标题】:Complex Join/Query with OrmLite ServiceStack使用 OrmLite ServiceStack 进行复杂的连接/查询
【发布时间】:2017-05-29 23:42:24
【问题描述】:

我无法将 EF linq Sample 转换为 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);

【问题讨论】:

    标签: c# servicestack ormlite-servicestack


    【解决方案1】:

    OrmLite 提供对普通 SQL 的类型化 1:1 API 映射,因此转换生成的 SQL 通常比 EF 查询更容易,因为 EF 查询通常不清楚正在生成什么查询。

    默认情况下 OrmLite SELECT 的源表在这种情况下是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 一次选择多个表,例如:

    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;
    }
    

    对于任何其他自定义结果,您需要使用要选择的结果指定自定义选择,例如:

    q.Select<OrderProduct,Order,Product>((op,o,p) => 
        new {
            op,     // all fields from OrderProduct table
            o.Id,
            p.Name,
            etc...
        });
    

    但是您需要在包含与上述查询匹配的公共属性的自定义架构中访问自定义结果集,例如:

    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)
    

    您需要查询表上的字段(就像在普通SQL中一样),您也可以查询多个相同条件的表:

    .Where<OrderProduct,Order>((op,o) => ...);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-16
      • 2019-05-19
      • 2019-01-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多