我正在处理一个应用程序的一部分,该应用程序只是从数据库中提取信息并将其显示给用户。为简单起见,让我们假设有一个数据库,其中有两个表:Cats
和Dogs
。两个表都手动分配了主键,并且永远不会重复/重叠。我试图实现的目标是执行一个LINQ查询,将concat
两个表。
我最近问了这个问题,关于在两个对象集合上执行LINQ concat
, Cats
和Dogs
,这是在代码中手动创建的。我建议你阅读前面的问题,因为它会让你对这个问题有更多的了解。
.Select
每列我需要一个匿名类型。对于这个实例来说,这将很好地工作,但将消耗包含我正在处理的数据的页面。
上一个问题和这个问题的不同之处在于,我试图从数据库中提取这些动物。从我的分析来看,.NET
或Entity Framework
似乎无法将我的database
与我的interface
联系起来
Model (From old question)
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.
从上面的错误中,看起来我不能使用接口与数据库交互,因为它没有映射到任何特定的表。
任何见解将不胜感激。由于
编辑作为对@里德·科普西的回应,有了你的解决方案,我得到了与我的例子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]'.
数据库对您的接口一无所知,您可能无法使其工作。我看到两个选项
你可以使用继承——例如由实体框架支持的——从一个共同的基础实体继承两个实体。然后,您将能够对基本类型执行查询,但这可能需要根据您在数据库级别实现继承的方式更改数据模型。
查看TPT继承和TPH继承的文档。还有其他继承模型,如TPC继承,但它们目前缺乏设计器支持。
第二个选项是从两个表中取出结果到内存中,并使用LINQ to Objects将它们合并到一个集合中。
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);
似乎设计得不是很好——结果肯定取决于所使用的数据库,但如果您通常只得到前四只猫而从未看到任何狗,我不会感到惊讶。