我正在尝试编写一个简单的场景。在我们的大多数应用程序中,我们有一个允许用户编辑下拉列表 - 查找表的值的系统。
下拉表通常非常小,仅包含几个字段:
他们可能有其他字段,这显然会因表格而异。 id,LastModifiedBy和LastModifiedDate属性都在基本实体类中定义,我们所有其他实体都从该类派生。
我们需要能够查询一个实体的EF上下文,除了三个常见字段之外,它是完全未知的(包括其名称/类型和字段),直到运行时。这否定了泛色,否则就是美妙的。我们能够自己解决很多反射问题 - 这将处理未知列,因为我们可以枚举我们的属性并从那里开始。我们看到的更难的问题是尝试查询EF,并在我们直到运行时才知道该表时获取可序列化的实体。
所以我想最简单的方法是:如何查询EF,并使用实体的字符串名称从中获取可序列化的实体?
我们要实现的是一种方法,其签名如下所示:
public BaseEntity RetrieveEntity(string entityType, int? id);
一旦我们拥有了这个核心,我们应该能够轻松地将其适应我们的其他场景(插入,更新,检索网格的分页列表等)。
这样我们就可以使用具体的东西了,我们可以使用上面的表定义。我们将调用实体StatusCode
,并假设其定义如下:
public partial class StatusCode : BaseEntity // BaseEntity gives us id, LastModifiedBy, LastModifiedDate
{
public string StatusCodeDescription { get; set; }
}
public class StatusCodeMap : EntityTypeConfiguration<StatusCode>
{
// boilerplate comments removed for brevity
this.HasKey(t => t.id);
this.Property(t => t.StatusCodeDescription)
.IsRequired()
.HasMaxLength(255);
this.ToTable("StatusCode");
this.Property(t => t.id).HasColumnName("StatusCodeId");
this.Property(t => t.StatusCodeDescription).HasColumnName("StatusCodeDescription");
this.Property(t => t.LastModifiedBy).HasColumnName("LastModifiedBy");
this.Property(t => t.LastModifiedDate).HasColumnName("LastModifiedDate");
}
IF 我可以明确地声明所有下拉列表都有描述,没有其他内容,然后我可以创建一个抽象类,下拉列表从中派生并处理它。我仍然必须能够通过名称动态查询并检索该对象的实例。说实话,我无法保证是这种情况。其中一些将具有其他字段 - 这里或那里的布尔属性,可能是映射到描述的代码以用于后端集成等。所以仅使用基类不是解决方案,并且不会充分发挥。
PS:我确定这实际上是一个骗局。我知道我不能成为第一个遇到这个问题的人。如果我们能在SO上的其他地方找到解决方案,我很高兴关闭它。然而,我整整一个下午都在谷歌试图找到解决这个问题的整体解决方案,并且惨遭失败。也就是说,我的Google-Fu今天可能让我失望了。答案 0 :(得分:1)
你说你有一个BaseEntity
类,所有这些类都继承自它。
您使用什么类型的继承? TPH?
您是否在上下文中添加了public DbSet<BaseEntity> BaseEntities { get; set; }
?
我很确定如果你这样做,那么你的方法可以像这样实现:
public BaseEntity RetrieveEntity(string entityType, int? id)
{
var e = context.BaseEntities.Find(id.GetValueOrDefault(-1));
if(e.GetType() != entityType)
return null;
return e;
}
不知道为什么你想这样做。我有这个:
public BaseEntity RetrieveEntity(int id)
{
return context.BaseEntities.Find(id);
}
并像这样使用
StatusCode sc = RetrieveEntity(int id) as StatusCode;
if(sc != null)
//etc
或者这个:
public T RetrieveEntity<T>(int id) where T: BaseEntity
{
return context.BaseEntities.Find(id) as T
}
并像这样使用它:
StatusCode sc = RetrieveEntity<StatusCode>(int id)
if(sc != null)
//etc
编辑,或者您可以像这样使用通用DbSet
public T RetrieveEntity<T>(int id) where T: BaseEntity
{
return context.DbSet<T>().Find(id)
}