使用OrmLite ServiceStack进行复杂的连接/查询

时间:2017-05-29 09:39:06

标签: c# servicestack 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);

1 个答案:

答案 0 :(得分:2)

OrmLite在普通SQL上提供了一个类型化的1:1 API映射,因此转换生成的SQL通常比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) => ...);