2017-05-29 3 views
1

Ich habe Probleme, eine EF Linq-Probe in OrmLite zu konvertieren. Ich habe die meisten der Abfrage genagelt, aber einige tiefe Joins oder Unterabfragen bringt einige Probleme.Complex Join/Abfrage mit OrmLite ServiceStack

Das ist meine EF-Abfrage:

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

Wie Sie sehen, ich bin mit der include() Funktion in der Joins. Das ist der Teil, in dem ich feststecke.

Das ist mein OrmLite query:

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

Antwort

2

OrmLite bietet ein typisierte 1: 1 API-Mapping über normale SQL, so dass es im Allgemeinen einfacher ist, erzeugt SQL zu konvertieren als EF fragt, wo es zu welcher Abfrage oft unklar ist, wird generiert.

standardmäßig OrmLite SELECT ist die Quelltabelle in diesem Fall die OrderProduct ist:

var q = _erpDbConnection.From<OrderProduct>() 

Welche was zurückgegeben wird, wenn Sie die Abfrage ausführen, das heißt:

List<OrderProduct> results = db.Select(q); 

um einige der anderen Daten, die Sie enthalten müssen Definieren Sie POCO References auf Ihrer Quelle OrderProduct, die dann unter Verwendung der Load* APIs geladen werden kann (z. B.

)
List<OrderProduct> results = db.LoadSelect(q); 

Sie können auch mehrere Tabellen auf einmal mit SelectMulti auswählen, zB:

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

Für jede andere Gewohnheit führt Sie ein Benutzerdefiniert Wählen Sie mit den Ergebnissen angeben müssen Sie ausgewählt werden sollen, zum Beispiel:

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

Aber dann werden Sie die benutzerdefinierte Ergebnismenge zugreifen müssen entweder in einem benutzerdefinierten Schema öffentliche Eigenschaften enthält, die die obige Abfrage übereinstimmt, zB:

var results = db.Select<OrderProductView>(q); 

Oder mit einem der OrmLite's dynamic result set APIs.


Beachten Sie auch, Sie nicht verschachtelte Abfragen in OrmLite wie tun können:

.Where<OrderProduct>(x => x.ProductId != null 
    && !x.Order.ContainsFreeMaterial 
    && !x.Order.IsFitSizeOrder 
    && x.Order.OrderType != OrderType.Stock) 

Sie müssen das Feld auf den Tisch Abfrage (wie bei der normalen SQL tun würde), können Sie auch Abfrage mehrere Tabellen in demselben Zustand mit:

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