【问题标题】:Assigning [Key] attribute to Entity Framework generated class - MVC4 C#将 [Key] 属性分配给实体框架生成的类 - MVC4 C#
【发布时间】:2017-09-04 14:25:16
【问题描述】:

我正在 Visual Studio 2012 中处理 MVC 4 (C#) 项目。我正在使用实体框架,它利用 *.edmx 文件对现有数据库进行建模。我的目标是实施数据库审计以跟踪对数据库所做的任何更改。类是使用数据库表中的字段自动生成的——我相信这是非常标准的东西。

我在尝试检索这些生成的类的主键时遇到了问题。实体框架不会将 [Key] 属性分配给类属性。我试图通过扩展创建的部分类并自己分配这个属性来解决这个问题。将其直接添加到生成的类中可以正常工作。如果我尝试“伙伴类”方法,稍后在执行代码时会收到以下错误:“实体 {Class Name} 没有 [Key] 属性。”

自动生成的类:

public partial class List
{
   public List()
   {
       this.Tasks = new HashSet<Task>();
   }

   public int Id { get; set; }
   public string ListName { get; set; }
}

扩展(好友)类:

[MetadataType(typeof(ListMetaData))]
public partial class List
{

    private class ListMetaData 
    {
        [Key]
        public int Id { get; set; }

    }

}

代码sn-p:

var property = dbEntry.Entity.GetType().GetProperties().FirstOrDefault(
   p => p.GetCustomAttributes(typeof(KeyAttribute), true).Any());

if (property == null)
    throw new InvalidOperationException(string.Format(
    "Entity {0} has no [Key] attribute.", dbEntry.Entity.GetType().Name));

string keyName = property.Name; 

我正在重写 DbContext 中的 SaveChanges() 方法来跟踪所做的更改。上面的 sn-p 显示了一个函数的一部分代码,该函数检查 DbEntityEntry 对象 (dbEntry) 以获取主键。

【问题讨论】:

    标签: c# entity-framework asp.net-mvc-4


    【解决方案1】:

    List 类是实体框架类还是 ListMetaData 类?如果是List 类,则该类中的Id 属性根本没有任何属性。嵌套的ListMetaData 类的Id 属性具有属性,这是一个完全不同的属性。

    如果您希望 ListMetaData 类具有该属性,我会将该类的表添加到模型中(如果还没有的话),取消嵌套该类并将其公开。

    【讨论】:

    • MetadataTypeAttribute 的目的是在无法直接编辑主类时将独立类的元数据关联到应用该属性的主类。它是专门为这种情况而创建的。不幸的是,只有当 ASP.NET MVC 使用实体类而不是 Entity Framework 本身时,才会读取元数据。
    【解决方案2】:

    感谢大家的建议。我最终做的是修改 *.tt 模板以自动将 [Key] 属性和 System.ComponentModel.DataAnnotations 指令添加到动态生成的类文件中。

    【讨论】:

      【解决方案3】:

      您可以检查几件事。

      1. 您的分部类是否与您的实体类在同一个命名空间中?

      2. 你的部分类在同一个项目中吗?

      3. 尝试将ListMetaData 类的访问级别更改为公共 还是内部的,也许没有嵌套?

      【讨论】:

        【解决方案4】:

        我想出了这样的东西,希望它有所帮助,并且是你所追求的:

        public string[] GetKeyNames<TEntity>() where TEntity : class
        {
            var set = ((IObjectContextAdapter)this).ObjectContext.CreateObjectSet<TEntity>();
            var entitySet = set.EntitySet;
            return entitySet.ElementType.KeyMembers.Select(k => k.Name).ToArray();
        }
        

        我已将它创建为 DBContext 本身的公共方法。然后你可以这样称呼它:

        var keys = context.GetKeyNames<List>();
        

        this 为灵感。

        您不需要元数据类来识别密钥 - 该信息将存储在 edmx 文件中。您通常使用元数据来添加验证,例如 [Required] 等。

        【讨论】:

          【解决方案5】:

          使用 EF 6.1,您还可以创建扩展方法来获取主键。 以下是示例,并且工作正常。

          PS:我不确定 100% 是否适用于复合键和复合键。

          using System;
          using System.Data.Entity;
          using System.Data.Entity.Core.Metadata.Edm;
          using System.Data.Entity.Infrastructure;
          using System.Linq;
          
          namespace System.Data.Entity
          {
              public static class DbContextExtensions
              {
                  public static string[] GetKeyNames<TEntity>(this DbContext context)
                      where TEntity : class
                  {
                      return context.GetKeyNames(typeof(TEntity));
                  }
          
                  public static string[] GetKeyNames(this DbContext context, Type entityType)
                  {
                      var metadata = ((IObjectContextAdapter)context).ObjectContext.MetadataWorkspace;
          
                      // Get the mapping between CLR types and metadata OSpace
                      var objectItemCollection = ((ObjectItemCollection)metadata.GetItemCollection(DataSpace.OSpace));
          
                      // Get metadata for given CLR type
                      var entityMetadata = metadata
                              .GetItems<EntityType>(DataSpace.OSpace)
                              .Single(e => objectItemCollection.GetClrType(e) == entityType);
          
                      return entityMetadata.KeyProperties.Select(p => p.Name).ToArray();
                  }
              }
          }
          

          Original Source

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2015-04-18
            • 1970-01-01
            • 1970-01-01
            • 2012-10-26
            • 1970-01-01
            • 2011-01-21
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多