所以,我的情况是我使用EF6和Component表使用每个层次结构模式的表。我有一个抽象的Component类和一些继承它的类,比如FirstNameComponent。
电话看起来像这样:
var sql = "Select * from Components";
var components = DbContext.Database.SqlQuery<Component>(sql).ToList();
在这种情况下,我必须SqlQuery
或DbContext
使用DbSet
。
正如您所期望的那样,这会查询表中的所有组件并尝试将它们映射到Component类,但由于它是抽象的,因此会抛出异常。
有没有办法使用自定义模型绑定器或表中的discriminator列来告诉SqlQuery调用哪些类用于每个组件?或者可能采用不同的方式将行序列化/反序列化为Component类?
答案 0 :(得分:0)
您可以在抽象类中定义一个鉴别器属性(基本上是您想要作为鉴别器的列的名称,作为字符串)
说,您将Component
类作为抽象类,FirstNameComponent
继承该类。
所以,你希望你的Component
课看起来像 -
public abstract class Component
{
public const string Discriminator = "ComponentType";
// Other properties/methods
}
现在,您的FirstNameComponent
课程看起来像 -
public class FirstNameComponent : Component
{
public const string TypeOfComponent = nameof(FirstNameComponent);
public override string ComponentType // your discriminator column
{
get
{
return TypeOfComponent;
}
}
// Other properties/methods
}
并在您的上下文中使用Fluent API构建模型时使用此属性。
public class ComponentContext: DbContext
{
public DbSet<FirstNameComponent> FirstNameComponents { get; set; }
// Other mappings
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Component>()
.Map<FirstNameComponent>(
configuration =>
configuration.Requires(Component.Discriminator).HasValue(FirstNameComponent.TypeOfComponent))
}
}
因此,您的查询将类似于 -
var components = ComponentContext.Components.OfType<FirstNameComponent>();
甚至 -
var components = ComponentContext.Components.Where(c => c is FirstNameComponent).ToList();
<强>更新强>
查看更新后的问题,以下是如何重新构建查询以获取特定类型的Component
-
string sqlQuery = @"Select * from Components Where ComponentType = @componentType";
string componentType = nameof(FirstNameComponent); //Can be made more dynamic
// Pass the type of component you need to cast to as a parameter
SqlParameter parameter = new SqlParameter("@componentType", componentType);
var components = DbContext.Database.SqlQuery<FirstNameComponent>(sqlQuery, parameter);
这应该会给你想要的结果。
更新2
所以,在对此进行了一些研究之后,我找到了this博客,其中讨论了使用Linq to Entities和EntitySQL的多态查询。
根据参考资料,您可以尝试另外一种方法来获取所有Components
-
string sqlQuery = @"SELECT VALUE c FROM Components AS c";
System.Data.Entity.Core.Objects.ObjectContext objectContext = ((IObjectContextAdapter)ComponentContext).ObjectContext;
System.Data.Entity.Core.Objects.ObjectQuery<Component> objectQuery = objectContext.CreateQuery<Component>(sqlQuery);
List<Component> components = objectQuery.ToList<Component>();
如果您拥有所有Components
,则可以使用Where
字段上的简单ComponentType
子句过滤掉所需的类型 -
var firstNameComponents = components.Where(c => c.ComponentType == nameof(FirstNameComponent)).ToList();