实体框架4:如何找到主键?

run*_*ier 13 .net c# entity-framework primary-key entity-framework-4

我正在尝试使用EF4创建一个通用方法来查找对象的主键.

public string GetPrimaryKey<T>()
{
    ...
}
Run Code Online (Sandbox Code Playgroud)

为了提供更多信息,我正在使用Tekpub StarterKit,下面是我试图启动和运行的类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.Objects;
using System.Data.Objects.ELinq;
using System.Data.Linq;
using Web.Infrastructure.Storage.EF4;

namespace Web.Infrastructure.Storage {
public class EFSession:ISession {
    PuzzleEntities _db;//This is an ObjectContext
    public EFSession() {
        _db = new PuzzleEntities();
    }

    public void CommitChanges() {
        _db.SaveChanges();
    }
    /// <summary>
    /// Gets the table provided by the type T and returns for querying
    /// </summary>
    private ObjectSet<T> GetObjectSet<T>() where T:class {
        return _db.CreateObjectSet<T>();
    }

    private T GetByPrimaryKey<T>() where T: class
    {
        .....
    }

    public void Delete<T>(System.Linq.Expressions.Expression<Func<T, bool>> expression) where T: class{

        foreach (T item in All<T>().Where(expression))
        {
            GetObjectSet<T>().DeleteObject(item);
        }
    }

    public void Delete<T>(T item) where T : class {
        GetObjectSet<T>().DeleteObject(item);
    }

    public void DeleteAll<T>() where T : class {
        foreach(T item in All<T>())
        {
            GetObjectSet<T>().DeleteObject(item);
        }
    }

    public void Dispose() {
        _db.Dispose();
    }

    public T Single<T>(System.Linq.Expressions.Expression<Func<T, bool>> expression) where T:class {
        return GetObjectSet<T>().SingleOrDefault(expression);
    }

    public IQueryable<T> All<T>() where T : class {
        return GetObjectSet<T>().AsQueryable();
    }

    public void Add<T>(T item) where T : class {
        GetObjectSet<T>().AddObject(item);
    }
    public void Add<T>(IEnumerable<T> items) where T : class {
        foreach (T item in items)
        {
            GetObjectSet<T>().AddObject(item);
        }
    }
    public void Update<T>(T item) where T : class {
        //nothing needed here
    }
}
}
Run Code Online (Sandbox Code Playgroud)

run*_*ier 17

所以我终于能够找到如何让它发挥作用.我希望我没有丢失我昨晚读到的博客的链接,因为我没有写代码.

public T GetByPrimaryKey<T>(int id) where T : class
{
    return (T)_db.GetObjectByKey(new EntityKey(_db.DefaultContainerName + "." + this.GetEntityName<T>(), GetPrimaryKeyInfo<T>().Name, id));
}

string GetEntityName<T>()
{
    string name = typeof(T).Name;
    if (name.ToLower() == "person")
        return "People";
    else if (name.Substring(name.Length - 1, 1).ToLower() == "y")
        return name.Remove(name.Length - 1, 1) + "ies";
    else if (name.Substring(name.Length - 1, 1).ToLower() == "s")
        return name + "es";
    else
        return name + "s";
}

private PropertyInfo GetPrimaryKeyInfo<T>()
{
    PropertyInfo[] properties = typeof(T).GetProperties();
    foreach (PropertyInfo pI in properties)
    {
        System.Object[] attributes = pI.GetCustomAttributes(true);
        foreach (object attribute in attributes)
        {
            if (attribute is EdmScalarPropertyAttribute)
            {
                if ((attribute as EdmScalarPropertyAttribute).EntityKeyProperty == true)
                    return pI;
            }
            else if (attribute is ColumnAttribute)
            {

                if ((attribute as ColumnAttribute).IsPrimaryKey == true)
                    return pI;
            }
        }
    }
    return null;
}
Run Code Online (Sandbox Code Playgroud)

我希望这有助于其他人.我只能说,如何做到这一点应该更清楚一些.

  • 技术上无效,因为如果存在复合主键,则会返回不正确的结果. (3认同)
  • 如果你通过流利的api建立你的FK,我怀疑它会起作用. (2认同)

Set*_*thO 16

每个EF4实体都有一个属性,EntityKey它包含一个数组EntityKeyValues(如果是复合键,则为数组).

您可以直接在您的实体实例上引用它,或者创建一个通用的帮助方法来完成此操作.如果我可以测试一些示例代码,我会在这里发布.

编辑:该EntityKeyValue是KeyValuePair<TKey, TValue>其中key是实体的主键字段和value是相关联的值.

例如,我有一个名为Company其主键是字段的实体Symbol.

var firstCompany = (from c in context.Companies select c).FirstOrDefault();
var kvp = firstCompany.EntityKey.EntityKeyValues[0];
// kvp shows {[Symbol, FOO]}
Run Code Online (Sandbox Code Playgroud)

在我的沙盒中,我注意到这个属性是null我在代码中创建实体的时候.但是一旦我从数据库中读取实体,它就被正确填充了.因此,看起来主键的EF4概念只有在它到达数据库时才能发挥作用.虽然如果您愿意,可以提前明确地设置它.

  • 如果有人迟到了...... EntityKey只存在于从EntityObject继承的对象上; 唯一能做到这一点的是模特优先的东西. (5认同)
  • 怎么没有那个属性? (2认同)

cur*_*Boy 5

我假设很多人只是通过查看“实体框架如何找到主键?”来停止这篇文章。不管 EF 版本(像我一样)。所以我想提一下,在 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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

原始来源