2011-09-01 73 views
2

的成員,我有以下實體的DbContext:LINQ查詢來獲取所有的實體指定類型

public class Customer 
{ 
    [Key] 
    public Guid Guid { get; set; } 

    [Required] 
    public string FullName { get; set; } 

    public virtual ICollection<Order> Orders { get; set; } 
} 

public abstract class Product 
{ 
    [Key] 
    public Guid Guid { get; set; } 

    [Required] 
    public String Title { get; set; } 
} 

public class Book : Product 
{ 
    public String Author { get; set; } 
    public String Year { get; set; } 
} 

public class DVD : Product 
{ 
    public String Genre { get; set; } 
    public String Country { get; set; } 
    public String MPAA { get; set; } 
    public String Year { get; set; } 
} 

public class Order 
{ 
    [Key, Column(Order = 0)] 
    public Guid CustomerGuid { get; set; } 

    [Key, Column(Order = 1)] 
    public Guid ProductGuid { get; set; } 

    public Int16 Quantity { get; set; } 

    public Decimal Price { get; set; } 

    public Decimal Total { get; set; } 

    public virtual Customer Customer { get; set; } 

    public virtual Product Product { get; set; } 
} 

public class StoreContext : DbContext 
{ 
    public DbSet<Customer> Customers { get; set; } 
    public DbSet<Book> Books { get; set; } 
    public DbSet<DVD> DVDs { get; set; } 
    public DbSet<Order> Orders { get; set; } 

    public StoreContext(string nameOrConnectionString) 
     : base(nameOrConnectionString) 
    { 

    } 
} 

什麼是查詢所有的訂單,其中產品是圖書的最佳方式?當我使用下面的查詢時,我得到了一堆SQL中的CASE。

var query = from order in context.Orders 
      where order.Product is Book 
      select order.Product as Book; 

UPDATE Aducci的解決方案是比我好多了,但是我還是重載SQL在更復雜的查詢。

例如,

var query = context.SaleOffers.Select(x => x.Realty).OfType<Flat>().Select(x => x.Planning.Name); 

SQL:

SELECT 
[Extent10].[Name] AS [Name] 
FROM [dbo].[SaleOffers] AS [Extent1] 
INNER JOIN [dbo].[Offers] AS [Extent2] ON [Extent1].[Guid] = [Extent2].[Guid] 
LEFT OUTER JOIN (SELECT [UnionAll5].[C1] AS [C1], [UnionAll5].[C2] AS [C2], [UnionAll5].[C3] AS [C3], [UnionAll5].[C4] AS [C4], [UnionAll5].[C5] AS [C5], [UnionAll5].[C6] AS [C6], [UnionAll5].[C7] AS [C7] 
    FROM (SELECT 
     [UnionAll4].[C1] AS [C1], 
     [UnionAll4].[C2] AS [C2], 
     [UnionAll4].[C3] AS [C3], 
     [UnionAll4].[C4] AS [C4], 
     [UnionAll4].[C5] AS [C5], 
     [UnionAll4].[C6] AS [C6], 
     [UnionAll4].[C7] AS [C7] 
     FROM (SELECT 
      [UnionAll3].[C1] AS [C1], 
      [UnionAll3].[C2] AS [C2], 
      [UnionAll3].[C3] AS [C3], 
      [UnionAll3].[C4] AS [C4], 
      [UnionAll3].[C5] AS [C5], 
      [UnionAll3].[C6] AS [C6], 
      [UnionAll3].[C7] AS [C7] 
      FROM (SELECT 
       [UnionAll2].[C1] AS [C1], 
       [UnionAll2].[C2] AS [C2], 
       [UnionAll2].[C3] AS [C3], 
       [UnionAll2].[C4] AS [C4], 
       [UnionAll2].[C5] AS [C5], 
       [UnionAll2].[C6] AS [C6], 
       [UnionAll2].[C7] AS [C7] 
       FROM (SELECT 
        [UnionAll1].[Guid] AS [C1], 
        [UnionAll1].[C1] AS [C2], 
        [UnionAll1].[C2] AS [C3], 
        [UnionAll1].[C3] AS [C4], 
        [UnionAll1].[C4] AS [C5], 
        [UnionAll1].[C5] AS [C6], 
        [UnionAll1].[C6] AS [C7] 
        FROM (SELECT 
         [Extent3].[Guid] AS [Guid], 
         CAST(NULL AS uniqueidentifier) AS [C1], 
         cast(0 as bit) AS [C2], 
         cast(0 as bit) AS [C3], 
         cast(0 as bit) AS [C4], 
         cast(0 as bit) AS [C5], 
         cast(0 as bit) AS [C6] 
         FROM [dbo].[Rooms] AS [Extent3] 
        UNION ALL 
         SELECT 
         [Extent4].[Guid] AS [Guid], 
         [Extent4].[PlanningGuid] AS [PlanningGuid], 
         cast(1 as bit) AS [C1], 
         cast(0 as bit) AS [C2], 
         cast(0 as bit) AS [C3], 
         cast(0 as bit) AS [C4], 
         cast(0 as bit) AS [C5] 
         FROM [dbo].[Flats] AS [Extent4]) AS [UnionAll1] 
       UNION ALL 
        SELECT 
        [Extent5].[Guid] AS [Guid], 
        CAST(NULL AS uniqueidentifier) AS [C1], 
        cast(0 as bit) AS [C2], 
        cast(1 as bit) AS [C3], 
        cast(0 as bit) AS [C4], 
        cast(0 as bit) AS [C5], 
        cast(0 as bit) AS [C6] 
        FROM [dbo].[CommercialProperties] AS [Extent5]) AS [UnionAll2] 
      UNION ALL 
       SELECT 
       [Extent6].[Guid] AS [Guid], 
       CAST(NULL AS uniqueidentifier) AS [C1], 
       cast(0 as bit) AS [C2], 
       cast(0 as bit) AS [C3], 
       cast(1 as bit) AS [C4], 
       cast(0 as bit) AS [C5], 
       cast(0 as bit) AS [C6] 
       FROM [dbo].[Houses] AS [Extent6]) AS [UnionAll3] 
     UNION ALL 
      SELECT 
      [Extent7].[Guid] AS [Guid], 
      CAST(NULL AS uniqueidentifier) AS [C1], 
      cast(0 as bit) AS [C2], 
      cast(0 as bit) AS [C3], 
      cast(0 as bit) AS [C4], 
      cast(1 as bit) AS [C5], 
      cast(0 as bit) AS [C6] 
      FROM [dbo].[Garages] AS [Extent7]) AS [UnionAll4] 
    UNION ALL 
     SELECT 
     [Extent8].[Guid] AS [Guid], 
     CAST(NULL AS uniqueidentifier) AS [C1], 
     cast(0 as bit) AS [C2], 
     cast(0 as bit) AS [C3], 
     cast(0 as bit) AS [C4], 
     cast(0 as bit) AS [C5], 
     cast(1 as bit) AS [C6] 
     FROM [dbo].[Lots] AS [Extent8]) AS [UnionAll5] 
    INNER JOIN [dbo].[Realties] AS [Extent9] ON [UnionAll5].[C1] = [Extent9].[Guid]) AS [Join2] ON [Extent2].[RealtyGuid] = [Join2].[C1] 
LEFT OUTER JOIN [dbo].[References] AS [Extent10] ON ([Extent10].[Discriminator] = 'FlatPlanning') AND ((CASE WHEN ([Join2].[C1] IS NULL) THEN CAST(NULL AS uniqueidentifier) WHEN ([Join2].[C4] = 1) THEN CAST(NULL AS uniqueidentifier) WHEN ([Join2].[C3] = 1) THEN [Join2].[C2] WHEN ([Join2].[C5] = 1) THEN CAST(NULL AS uniqueidentifier) WHEN ([Join2].[C6] = 1) THEN CAST(NULL AS uniqueidentifier) WHEN ([Join2].[C7] = 1) THEN CAST(NULL AS uniqueidentifier) END) = [Extent10].[Guid]) 
WHERE CASE WHEN ([Join2].[C1] IS NULL) THEN CAST(NULL AS varchar(1)) WHEN ([Join2].[C4] = 1) THEN '3X0X' WHEN ([Join2].[C3] = 1) THEN '3X1X' WHEN ([Join2].[C5] = 1) THEN '3X2X' WHEN ([Join2].[C6] = 1) THEN '3X3X' WHEN ([Join2].[C7] = 1) THEN '3X4X' ELSE '3X5X' END LIKE '3X1X%' 

提前感謝!

回答

5

不知道,如果生成的SQL會好一點

var query = context.Orders.Select(order => order.Product).OfType<Book>(); 
+0

謝謝您的回覆。請參閱我的更新。 –

0

不是直接回答你的問題,但我不知道你會得到更好的SQL如果添加了類型鑑別列產品:

public abstract class Product 
{ 
    [Key] 
    public Guid Guid { get; set; } 

    [Required] 
    public String Title { get; set; } 

    public ProductType Type { get; set; } 
} 

然後,您可以在您的查詢中使用它,並可能避免加載不屬於特定類型的產品。

+0

謝謝你的回覆。通過這種方法,我需要將所有後代的屬性放在Product類中。這不適合。 –

+0

你的意思是你需要把所有的DVD屬性放在產品類中?你不 - 只是一個標誌,表明有問題的產品是DVD。 – David

+0

我仍然必須將產品轉換爲DVD才能訪問DVD的屬性? –

0

在使用某些繼承模型時,我已經在生成的TSQL中看到過這種噁心。我固定使用EntitySQL而不是LINQ

類似
SELECT VALUE b 
FROM OFTYPE(MyNs.Products, MyNs.Book) 
AS b 

EF短ciruited是使用由於某種原因,ESQL OFTYPE操作時,使用LINQ.OfType創建嵌套子查詢。 (另請參閱http://msdn.microsoft.com/en-us/library/bb399295.aspx#Y639

+0

謝謝你的回覆。我之前沒有使用過EntitySQL,因爲它是基於字符串的。 LINQ幫助我避免了大量的設計時錯誤,我想通過使用LINQ來解決這個問題。 –

+0

@Boris,我是那裏最大的LINQ粉絲之一,但有些東西,提供者不能做得太好。那時候,我們不得不放棄其他選擇(如果他們工作的話)。在正確的時間使用正確的工具。 –

+0

完全同意你的看法!但EntitySQL對我來說仍然不是最好的選擇。我想我會改變LINQ查詢以避免類型轉換。 –

相關問題