C# LINQ导航属性多个源
我有一个存储不同位置的数据库。根据位置的类型,唯一的详细信息存储在与常用属性不同的表中,即名称、坐标、描述存储在位置表中,而人口存储在CityDetails表中。 这些表通过特定详细信息表中的FK连接。 由于有不止一个特定的详细信息表,我正在琢磨如何查询这些多个表。 我的位置对象如下所示:C# LINQ导航属性多个源,c#,sql,linq,linq-to-entities,linq-to-objects,C#,Sql,Linq,Linq To Entities,Linq To Objects,我有一个存储不同位置的数据库。根据位置的类型,唯一的详细信息存储在与常用属性不同的表中,即名称、坐标、描述存储在位置表中,而人口存储在CityDetails表中。 这些表通过特定详细信息表中的FK连接。 由于有不止一个特定的详细信息表,我正在琢磨如何查询这些多个表。 我的位置对象如下所示: [Table("Locations")] public class LocationData { public Guid Id { get; set; } // multiple diffe
[Table("Locations")]
public class LocationData
{
public Guid Id { get; set; }
// multiple different properties here.
public string Type { get; set; }
public DetailsData { get; set; }
}
public abstract class DetailsData
{
[Key, ForeignKey("Location")]
public Guid { get; set; }
public LocationData Location { get; set; }
}
根据Type属性,我可以查看必须查询的详细信息表。详细信息表至少如下所示:
[Table("Locations")]
public class LocationData
{
public Guid Id { get; set; }
// multiple different properties here.
public string Type { get; set; }
public DetailsData { get; set; }
}
public abstract class DetailsData
{
[Key, ForeignKey("Location")]
public Guid { get; set; }
public LocationData Location { get; set; }
}
然后,表示位置类型的每个表都从DetailsData类继承,并配置为使用每个具体类继承层次结构的表。
下面是一个特定详细信息表的示例:
[Table("CityDetails")]
public class CityDetailsData : DetailsData
{
public string Planet { get; set; }
public int Population { get; set; }
}
如何在Location类中填充DetailsData属性。以下是我当前的LINQ查询:
from l in Locations
select new
{
Id = l.Id,
Name = l.Name,
Description = l.Description,
Coordinates = l.Coordinates,
Type = l.Type,
DetailsData = CityDetails // Here lies the problem. How can I populate this property properly?
}
好的,我假设您的详细信息表都有不同的列集,希望能够使用IEnumerable实例,并且希望能够直接访问返回的任何详细信息表对象的实例的属性 那是个强悍的家伙。基本上有三种方法可以为未知类型的对象编写代码: 给它一个对象类型。 使所有细节表从公共接口继承,并使CityDetails成为实现该接口的对象。 使用泛型类型,这意味着您最终指定了类型,但您可以将该决策向上推到所实现类型的声明者。 使用System.Object意味着您需要将所有DetailsData对象强制转换为所需的类型,或者使用反射来访问它们的属性,而使用接口意味着您可以直接访问某些属性,但可能不是您想要的所有属性 我认为泛型可能是最好的混合解决方案 我会这样做:
[Table("Locations")]
public class LocationData
{
public Guid Id { get; set; }
// multiple different properties here.
public string Type { get; set; }
public DetailsData { get; set; }
}
public abstract class DetailsData
{
[Key, ForeignKey("Location")]
public Guid { get; set; }
public LocationData Location { get; set; }
}
承认没有完美的解决方案。
如果您使用的是ASP.NET MVC,请定义类似于ViewModel的类,而不是像在示例代码中那样创建匿名类型:
public class LocationViewModel<TDetailsData>
{
public Guid Id { get; set; }
// multiple different properties here.
public string Type { get; set; }
public TDetailsData DetailsData { get; set; }
}
如果需要保留这些对象的IEnumerable,请定义一个接口ILocationDataViewModel和另一个接口ILocationDataViewModel,使LocationViewModel实现这两个接口,并根据情况使用IEnumerable或IEnumerable等
如果我理解正确,您希望动态确定类型并动态处理它。那样的话,你可以和我一起去。我还没有测试过这段代码,但是你可以这样想
public DetailsData GetDetailsData(Type t)
{
dynamic typVal = new ExpandoObject();
if(t == typeof(CityDetails))
{
typVal = new CityDetails();
}
// add other types
return (DetailsData)PopulateDetailsData(typVal);
}
public DetailsData PopulateDetailsData(CityDetails cd)
{
cd.Planet = new CityDetails().Planet;
return cd;
}
// Add other type related methods with same
// signature with input parameter differentiated by types
// for example
public DetailsData PopulateDetailsData(TownDetails td)
{
td.Income = new TownDetails().Income;
return td;
}
在查询中,您可以有如下内容
from l in Locations
select new
{
Id = l.Id,
Name = l.Name,
Description = l.Description,
Coordinates = l.Coordinates,
Type = l.Type,
DetailsData = GetDetailsData(l.Type)
}
我假设您所有的特定明细表都有不同的列集?是的,它们有。我用一个例子更新了问题。请参阅我更新的问题。每个细节表都有一组不同的属性/列,但都继承自同一抽象类DetailsData。此抽象类也是在主LocationData类中用作属性类型的类的类型。我要补充的是,这些数据将被转换成一种稍有不同的数据类型,用于程序的其他部分。基本上,我需要一个带有LocationData的IEnumerable。详细信息从不同的详细信息表之一填充。如果在使用LocationData的特定实例时不关心intellisense或易于访问属性值,难道你不能编写一个助手方法,使用参数类型来检查适当的细节表并返回一个DetailsData吗?不,我不太了解intellisense。我的工作流程如下:1。查询位置表。2.查询适当的详细信息表并将其存储在details属性中。3.将其返回到存储库。4.将其传递到转换器5。将转换后的数据返回给用户。我试试你的主意。它是如此简单,我完全忘记了它…@Ruhrpottpatriot LOL!我给了你一个过于复杂的答案,因为我想,问题不可能那么简单!他一定在要求一些非常微妙的东西!可能就是这么简单。问题是:我创建了一个请求,让服务经理来处理,这与存储库的工作方式有关,因为它可以使用多个源,即基于请求和服务经理的数据库或webApi数据。对数据库的请求是Func表达式。我不确定我是否可以做一些简单的事情,比如方法调用。或者更好:我确信这必须在林克完成。好吧,我错过了树木的森林。。。英雄联盟