如何通过表的字符串名称查询EF中的表?

时间:2013-12-19 00:12:31

标签: .net entity-framework

我正在尝试编写一个简单的场景。在我们的大多数应用程序中,我们有一个允许用户编辑下拉列表 - 查找表的值的系统。

下拉表通常非常小,仅包含几个字段:

  • id(PK,int identity 1,1)
  • 描述(nvarchar)
  • LastModifiedBy(nvarchar)
  • LastModifiedDate(smalldatetime)

他们可能有其他字段,这显然会因表格而异。 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今天可能让我失望了。

1 个答案:

答案 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)
}