2013-01-08 20 views
1

我正在處理一個簡單地從數據庫中提取信息並將其顯示給用戶的應用程序的一部分。爲了簡單起見,讓我們假設我有一個包含兩個表的數據庫:CatsDogs。兩個表都有人工分配的主鍵,並且從不重複/重疊。我試圖達到的目標是執行1個LINQ查詢,將concat這兩個表。在LINQ數據庫查詢中使用接口

我最近問this關於執行LINQ concat兩個集合的對象,CatsDogs,通過手動在代碼中創建的問題。我建議閱讀前面的問題,因爲它會給這個問題很多見解。

我希望使用接口的原因是爲了簡化我的查詢。我目前有一個解決方案,我需要的每個列都需要成爲匿名類型的.Select。這對這個實例工作正常,但會消耗與我正在使用的數據的頁面。

上一個問題和這個問題的不同之處在於我試圖從數據庫中提取這些動物。從我的分析,似乎.NETEntity Framework是不能夠涉及我databaseinterface

型號(舊題)

public interface iAnimal 
{ 
    string name { get; set; } 
    int age { get; set; } 
} 
public class Dog :iAnimal 
{ 
    public string name { get; set; } 
    public int age { get; set; } 
} 
public class Cat:iAnimal 
{ 
    public string name { get; set; } 
    public int age { get; set; } 
} 

這裏有一些不同的LINQ查詢我曾嘗試和導致錯誤。第一個例子將使用上一個問題的解決方案。

var model = _db.Cats.Concat<iAnimal>(_db.Dogs).Take(4); 

System.ArgumentException: DbUnionAllExpression requires arguments with compatible collection ResultTypes. 

無協方差:

var model = _db.Cats.Cast<iAnimal>().Concat(_db.Dogs.Cast<iAnimal>()); 

System.NotSupportedException: Unable to cast the type 'Test.Models.Cat' to type 'Test.Interfaces.iAnimals'. LINQ to Entities only supports casting Entity Data Model primitive types. 

從上面的錯誤,它看起來像我不能夠使用的接口,因爲它是不映射到任何特定的表與數據庫交互。

任何有識之士將不勝感激。由於

編輯 針對@Reed科普塞,與您的解決方案,我得到了同樣的錯誤我的例子without covariance。我試圖改變視圖的類型相匹配的錯誤建議是什麼,這將導致該錯誤

System.InvalidOperationException: The model item passed into the dictionary is of type 'System.Data.Entity.Infrastructure.DbQuery`1[Test.Interfaces.iAnimal]', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable`1[Test.Models.Cat]'. 
+0

當你Concat的在一起,怎麼能分辨出哪'iAnimal'引用其中的數據源?你可以在SQL中做到這一點,並能夠區分這兩個來源?換句話說,如果你做了'SELECT ID,Name,Age FROM Dogs UNION SELECT ID,Name,Age FROM Cats',你只看結果集,你能區分每個記錄的來源嗎? – SPFiredrake

+0

在NHibernate中,只有定義了一個鑑別符才能使用繼承。也許實體有類似的要求。 – Andre

+0

此頁面上沒有此類行爲要求。它是嚴格只讀的。 – Jeff

回答

1

你的數據庫一無所知你的界面,你可能無法得到這個工作。我看到兩個選項。

您可以使用繼承 - 例如由實體框架支持 - 並從一個公共基礎實體繼承這兩個實體。您將能夠對基本類型執行查詢,但這可能需要根據您在數據庫級別實現繼承的方式更改數據模型。

查看TPT inheritanceTPH inheritance的文檔。還有其他繼承模型,如TPC繼承,但他們目前缺乏設計器支持。

第二個選擇是從兩個表的結果抓取到內存,並使用LINQ到對象將它們合併成一個單一的集合。

var dogs = database.Dogs.Take(4).ToList(); 
var cats = database.Cats.Take(4).ToList(); 

var pets = dogs.Cast<IPet>().Concat(cats).ToList(); 

另外請注意,您的查詢

var model = _db.Cats.Concat<iAnimal>(_db.Dogs).Take(4); 

似乎沒有真正精心設計的 - 結果肯定會取決於所使用的數據庫,但我不會感到驚訝,如果你通常只得到第一個四隻貓和從來沒有看到任何狗。

+0

我相信我嘗試了這一點,但它沒有奏效。我會再試一次...請繼續關注。我寫的查詢更多的是一個概念證明。我不想要1000多件物品被退回。我只想首先測試'.Concat'的功能。 – Jeff

+0

該解決方案有效,但如果數據集很大,該怎麼辦?如果我記得,'ToList()'是一個貪婪的運算符。該解決方案將運行這兩個查詢。是否有可能操縱這隻觸摸數據庫一次? – Jeff

+0

這可能既不在這裏,也不在那裏,但我並沒有完全看到這(不僅僅是這個答案,而是一般情況下在這種情況下使用接口)如何簡化或以其他方式簡化'var query = db。 Cats.Concat(db.Dogs)'。 –