- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
所以,我的情况是,我使用的是 EF6 和一个组件表,该表使用每个层次结构模式的表。我有一个抽象组件类和一些继承它的类,例如 FirstNameComponent。
调用看起来像这样:
var sql = "Select * from Components";
var components = DbContext.Database.SqlQuery<Component>(sql).ToList();
在这种情况下,我必须使用 SqlQuery
关闭 DbContext
或 DbSet
。
如您所料,这将查询表中的所有组件并尝试将它们映射到 Component 类,但由于它是抽象的,因此会引发异常。
有没有一种方法可以使用自定义模型绑定(bind)器或表上带有鉴别器列的东西来告诉 SqlQuery 调用每个组件使用哪些类?或者可能采用不同的方式将行序列化/反序列化到组件类中?
最佳答案
您可以在抽象类中定义一个鉴别器属性(基本上是您想要作为鉴别器的列的名称,作为字符串)
比如说,您将 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
,你就可以在 ComponentType
字段上使用一个简单的 Where
子句来过滤出所需的类型 -
var firstNameComponents = components.Where(c => c.ComponentType == nameof(FirstNameComponent)).ToList();
关于C# 如何将 DbContext.Database.SqlQuery 与抽象/派生类一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43243593/
我是一名优秀的程序员,十分优秀!