C# 如何获取对象集<;T>';谁的实体密钥名?

C# 如何获取对象集<;T>';谁的实体密钥名?,c#,.net,entity-framework,C#,.net,Entity Framework,我已经在我的通用存储库中创建了一个通用ObjectSet 我想要得到的是ObjectSet的EntityKey的名称,这样我就可以在DataContext.GetObjectByKey中使用它了 我四处搜索,深入挖掘,但似乎在ObjectSet类中的任何地方都找不到该值。我刚才寻找了一种很好的方法来实现这一点,但没有找到。通常,我会在其中的某个地方构建一个GetEntityByKey扩展方法,包含字符串以构建TryGetObjectByKey调用的实体键。构建实体键的总体思路如下: intern

我已经在我的通用存储库中创建了一个通用
ObjectSet

我想要得到的是
ObjectSet
的EntityKey的
名称
,这样我就可以在
DataContext.GetObjectByKey
中使用它了


我四处搜索,深入挖掘,但似乎在
ObjectSet
类中的任何地方都找不到该值。

我刚才寻找了一种很好的方法来实现这一点,但没有找到。通常,我会在其中的某个地方构建一个GetEntityByKey扩展方法,包含字符串以构建TryGetObjectByKey调用的实体键。构建实体键的总体思路如下:

internal class Program
{
    private static void Main(string[] args)
    {
        var dc = new AdventureWorksLT2008Entities();
        object c;
        dc.TryGetObjectByKey(GetEntityKey(dc.Customers, 23), out c);
        var customer = c as Customer;
        Console.WriteLine(customer.EmailAddress);
    }

    private static EntityKey GetEntityKey<T>(ObjectSet<T> objectSet, object keyValue) where T : class
    {
        var entitySetName = objectSet.Context.DefaultContainerName + "." + objectSet.EntitySet.Name;
        var keyPropertyName = objectSet.EntitySet.ElementType.KeyMembers[0].ToString();
        var entityKey = new EntityKey(entitySetName, new[] {new EntityKeyMember(keyPropertyName, keyValue)});
        return entityKey;
    }
}
内部类程序
{
私有静态void Main(字符串[]args)
{
var dc=新的AdventureWorksLT2008Entities();
对象c;
dc.TryGetObjectByKey(GetEntityKey(dc.Customers,23),输出c);
var客户=c作为客户;
Console.WriteLine(customer.EmailAddress);
}
私有静态EntityKey GetEntityKey(ObjectSet ObjectSet,object keyValue),其中T:class
{
var entitySetName=objectSet.Context.DefaultContainerName+“+”objectSet.EntitySet.Name;
var keyPropertyName=objectSet.EntitySet.ElementType.KeyMembers[0].ToString();
var entityKey=new entityKey(entitySetName,new[]{new EntityKeyMember(keyPropertyName,keyValue)});
返回entityKey;
}
}
你也可以做类似的事情。为了简单起见,此示例假设每个EntityKey只有一个字段-对于多个值键,您需要使用
ObjectSet.ElementType.KeyMembers
执行稍微复杂的操作,并将所有键传递到EntityKey构造函数中。

请参阅我关于获取EntitySetName的说明。对于我的存储库,我创建了一个属性,该属性获取特定类名的实体集名称,以执行您正试图执行的操作。

通用:

public class GenericoRepositorio<T> : IGenericoRepositorio<T> where T : class
{
    protected readonly ObjectSet<T> ObjetoSet;
    protected readonly ModeloContainer Contexto;

    public GenericoRepositorio(ModeloContainer contexto)
    {
        Contexto = contexto;
        ObjetoSet = Contexto.CreateObjectSet<T>();
    }

    public T Carregar(int id)
    {
        object objeto;
        Contexto.TryGetObjectByKey(GetEntityKey(ObjetoSet, id), out objeto);
        return (T)objeto;
    }

    private static EntityKey GetEntityKey<T>(ObjectSet<T> objectSet, object keyValue) where T : class
    {
        var entitySetName = objectSet.Context.DefaultContainerName + "." + objectSet.EntitySet.Name;
        var keyPropertyName = objectSet.EntitySet.ElementType.KeyMembers[0].ToString();
        var entityKey = new EntityKey(entitySetName, new[] { new EntityKeyMember(keyPropertyName, keyValue) });
        return entityKey;
    }
}
公共类GenericoRepositorio:IGenericoRepositorio其中T:class
{
受保护的只读对象集对象集;
受保护的只读ModeloContainer Contexto;
公共通用存储库(ModeloContainer contexto)
{
Contexto=Contexto;
ObjetoSet=Contexto.CreateObjectSet();
}
公共T卡雷加(国际id)
{
对象对象;
TryGetObjectByKey(GetEntityKey(ObjetoSet,id),out objeto);
返回(T)对象;
}
私有静态EntityKey GetEntityKey(ObjectSet ObjectSet,object keyValue),其中T:class
{
var entitySetName=objectSet.Context.DefaultContainerName+“+”objectSet.EntitySet.Name;
var keyPropertyName=objectSet.EntitySet.ElementType.KeyMembers[0].ToString();
var entityKey=new entityKey(entitySetName,new[]{new EntityKeyMember(keyPropertyName,keyValue)});
返回entityKey;
}
}

这将为您提供对象集的所有通用参数(类型):

objectSet.GetType().GetGenericArguments().First()

我在尝试做几乎相同的事情时遇到了困难,当类型未知时,在运行时获取主键名称和值。我刚刚开始尝试实现一个删除审计方案,我发现的每一个解决方案都涉及到我不太理解的多余代码。EntityKey在DbContext中不可用,这也是令人困惑和恼火的。最后5行可以为你节省5小时和1年的脱发时间。我不会尝试对插入执行此操作,因此如果执行此操作,则需要仔细检查这些值,因为它们可能为0或null

foreach(var entry in ChangeTracker.Entries<IAuditable>())
{
...

case EntityState.Deleted:

var oc = ((IObjectContextAdapter)this).ObjectContext;  //this is a DbContext
EntityKey ek = oc.ObjectStateManager.GetObjectStateEntry(entry.Entity).EntityKey;
var tablename = ek.EntitySetName;
var primaryKeyField = ek.EntityKeyValues[0].Key;     //assumes only 1 primary key
var primaryKeyValue = ek.EntityKeyValues[0].Value;
foreach(ChangeTracker.Entries()中的var条目)
{
...
案例实体状态。已删除:
var oc=((IObjectContextAdapter)this).ObjectContext;//这是一个DbContext
EntityKey ek=oc.ObjectStateManager.GetObjectStateEntry(entry.Entity).EntityKey;
var tablename=ek.EntitySetName;
var primaryKeyField=ek.EntityKeyValues[0].Key;//假定只有1个主键
var primaryKeyValue=ek.EntityKeyValues[0]。值;
var objContext=((IObjectContextAdapter)this.context).ObjectContext;

var objSet=objContext.CreateObjectSet();

var entityKey=objContext.CreateEntityKey(objSet.EntitySet.Name,entityToUpdate);

objectfoundentity;

if (exits && this.dbset.Local != null && this.dbset.Local.Contains(foundEntity) &&this.dbset.Local.Any())                    
{
  if (entityKey.EntityKeyValues != null && entityKey.EntityKeyValues.Any())                       
  {       
    DbEntityEntry<T> entry = this.context.Entry(this.dbset.Find(entityKey.EntityKeyValues.FirstOrDefault().Value));
                        entry.CurrentValues.SetValues(entityToUpdate);
   }
}

this.context.SaveChanges();
var exits=objContext.TryGetObjectByKey(entityKey,out foundEntity);

if(exits&&this.dbset.Local!=null&&this.dbset.Local.Contains(foundEntity)&&this.dbset.Local.Any())
{
if(entityKey.EntityKeyValues!=null&&entityKey.EntityKeyValues.Any())
{       
DbEntityEntry=this.context.entry(this.dbset.Find(entityKey.EntityKeyValues.FirstOrDefault().Value));
entry.CurrentValues.SetValues(entityToUpdate);
}
}
this.context.SaveChanges();
使用EF 6测试

它将为给定DbEntityEntry的每个主键值返回一个对象数组

他们可能是边缘案例,但对于我的简单需求来说效果很好

希望这对其他人有帮助

object[] GetPrimaryKeyValue(DbEntityEntry entry)
{
    List<object> key = new List<object>();

    var objectStateEntry = ((IObjectContextAdapter)this).ObjectContext.ObjectStateManager.GetObjectStateEntry(entry.Entity);
    if (objectStateEntry.EntityKey.EntityKeyValues != null && objectStateEntry.EntityKey.EntityKeyValues.Length==1)
    {
        key.Add(objectStateEntry.EntityKey.EntityKeyValues[0].Value);
    }
    else
    {
        if (objectStateEntry.EntitySet.ElementType.KeyMembers.Any())
        {
            foreach (var keyMember in objectStateEntry.EntitySet.ElementType.KeyMembers)
            {
                if (entry.CurrentValues.PropertyNames.Contains(keyMember.Name))
                {
                    var memberValue = entry.CurrentValues[keyMember.Name];
                    if (memberValue != null)
                    {
                        key.Add(memberValue);
                    }
                }
            }
        }
    }
    return key.ToArray();
}
对象[]GetPrimaryKeyValue(DbEntityEntry)
{
列表键=新列表();
var objectStateEntry=((IOObjectContextAdapter)this.ObjectContext.ObjectStateManager.GetObjectStateEntry(entry.Entity);
if(objectStateEntry.EntityKey.EntityKeyValues!=null&&objectStateEntry.EntityKey.EntityKeyValues.Length==1)
{
添加(objectStateEntry.EntityKey.EntityKeyValues[0].Value);
}
其他的
{
if(objectStateEntry.EntitySet.ElementType.KeyMembers.Any())
{
foreach(objectStateEntry.EntitySet.ElementType.KeyMembers中的var keyMember)
{
if(entry.CurrentValues.PropertyNames.Contains(keyMember.Name))
{
var memberValue=entry.CurrentValues[keyMember.Name];
if(memberValue!=null)
{
key.Add(memberValue)