如何在实体框架6中获取实体的主键字段和默认值?

时间:2014-07-30 22:36:13

标签: c# .net entity-framework

我的数据库设计师没有使用标准" Id"对于我的数据库中的主键字段,所以我需要为我正在编写的通用存储库找到以下内容。

  • 主键名称
  • 主键CLR类型
  • 主键CLR类型默认值

我正在尝试使用如下所示的Generated脚手架代码并创建一个通用存储库:

    public void InsertOrUpdate(Entity entity)
    {
        if (entity.EntityID == default(int))
        {
            // New entity
            _context.Entry(entity).State = System.Data.Entity.EntityState.Added;
        }
        else
        {
            // Existing entity (TODO:  Wont add the whole graph of things)
            _context.Entry(entity).State = System.Data.Entity.EntityState.Modified;
        }
    }

我通过执行以下操作找到了主键名称:

    public string FindPrimaryKey()
{
    var objectSet = ((IObjectContextAdapter)_context).ObjectContext.CreateObjectSet<Entity>();
    string keyName = objectSet.EntitySet.ElementType.KeyMembers.Select(k => k.Name).FirstOrDefault();
    return keyName;
}

我接近使用以下代码获取主键CLR类型:

  public string FindPrimaryKeyType()
        {
            var objectSet = ((IObjectContextAdapter)_context).ObjectContext.CreateObjectSet<Entity>();
            string keyType = objectSet.EntitySet.ElementType.KeyMembers.Select(k => k.TypeUsage.EdmType.FullName).FirstOrDefault();
            var keyType2 = from m in objectSet.EntitySet.ElementType.KeyMembers
                select m.TypeUsage.EdmType;
            return "";
        }

我在调试上面的代码时可以看到ClrType,但我还没有弄清楚如何从ClrType中获取Type:

VS 2013 Debug screen shot

所以,请帮我弄清楚如何获取ClrType,或者更好地了解如何做到这一点。

2 个答案:

答案 0 :(得分:3)

您已经获得了表示属性名称的键名,只需使用反射来获取属性类型。

var objectSet = ((IObjectContextAdapter)_context).ObjectContext.CreateObjectSet<Entity>();
var keyNames = objectSet.EntitySet.ElementType.KeyMembers.Select(k => k.Name).ToArray();

获取clr类型。

var types = keyNames.Select(keyName => typeof(Entity).GetProperty(keyName).PropertyType).ToArray();

获取默认值。

var defaultValues = types.Select(type => type.IsValueType ? Activator.CreateInstance(type) : null).ToArray();

更新

在课堂上包装所有内容

public class EntityHelper<Entity> where Entity :class
{
    private DbContext _context;
    public EntityHelper(DbContext context)
    {
        _context = context;
    }
    public string[] FindPrimaryKeyNames()
    {
        var objectSet = ((IObjectContextAdapter)_context).ObjectContext.CreateObjectSet<Entity>();
        var keyNames = objectSet.EntitySet.ElementType.KeyMembers.Select(k => k.Name).ToArray();
        return keyNames;
    }
    public Type[] FindPrimaryKeyTypes()
    {
        var keyNames = FindPrimaryKeyNames();
        var types = keyNames.Select(keyName => typeof(Entity).GetProperty(keyName).PropertyType).ToArray();
        return types;
    }
    public object[] FindPrimaryKeyDefaultValues()
    {
        var types = FindPrimaryKeyTypes();
        var defaultValues = types.Select(type => type.IsValueType ? Activator.CreateInstance(type) : null).ToArray();
        return defaultValues;
    }
}

答案 1 :(得分:1)

我不知道从模型元数据公开的EdmType映射到本地.Net Type的任何直接方法。 Yuliam提供了一种混合方法,可以切换到.Net反射来解析类型。

如果您想坚持使用Entity Framework元数据,您可以自己进行映射,如下面的代码示例所示。这是我所处的代码,其灵感来自以下SO问题:Is there a mapper to/from EDM/OData types to CLR types?

private static Type GetTypedEdmValue(EdmType type)
{           
    switch (type.FullName)
    {
        case "Edm.String": return typeof(string);
        case "Edm.Byte": return typeof(byte);
        case "Edm.SByte": return typeof(sbyte);
        case "Edm.Int16": return typeof(short);
        case "Edm.Int32": return typeof(int);
        case "Edm.Int64": return typeof(long);
        case "Edm.Double": return typeof(double);
        case "Edm.Single": return typeof(float);
        case "Edm.Boolean": return typeof(bool);
        case "Edm.Decimal": return typeof(decimal);
        case "Edm.DateTime": return typeof (DateTime);                
        case "Edm.Guid": return typeof (Guid);

        default: throw new NotSupportedException("Not supported type " + type);
    }
}

要获取类型的默认值,您可以使用以下内容。同样,我所处的代码最初来自以下SO问题:Default value of a type at Runtime

object GetDefaultValue(Type t)
{
    if (t.IsValueType)
        return Activator.CreateInstance(t);

    return null;
}

然后使用如下:

var objectContext = (context as IObjectContextAdapter).ObjectContext;
var entitySet = objectContext.CreateObjectSet<YOUR_ENTITY>().EntitySet;
var keys = entitySet.ElementType.KeyMembers.Select(k =>
{
    var type = GetTypedEdmValue(k.TypeUsage.EdmType);                    
    return new
    {
        KeyName = k.Name,
        KeyType = type,
        KeyDefaultValue = GetDefaultValue(type)

    };
}).ToList();

为了示例的目的,这只是为了返回一个包含键名,类型和默认值的匿名类型列表。