2013-01-08 21 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)'。 –