Как получить имя ключа объекта ObjectSet <T>? - PullRequest
6 голосов
/ 25 июля 2010

Я создал универсальный ObjectSet<T> в своем универсальном репозитории.

Я хотел бы получить name EntityKey ObjectSet<T>, чтобы я мог использовать его в DataContext.GetObjectByKey.

Я искал и копал глубоко, но я не могу найти это значение нигде в классе ObjectSet.

Ответы [ 7 ]

5 голосов
/ 25 июля 2010

Некоторое время назад я искал хороший способ сделать это и не смог его найти.Я обычно заканчиваю тем, что где-то и внутри него создаю метод расширения 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;
    }
}

Возможно, вы сможете сделать что-то подобное.В этом примере предполагается простота одного поля на EntityKey - для ключей с несколькими значениями вам нужно будет сделать что-то более сложное с ObjectSet<T>.ElementType.KeyMembers и передать все ключи в конструктор EntityKey.

2 голосов
/ 10 декабря 2010

Общий:

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;
    }
}
1 голос
/ 20 декабря 2011

Это должно дать вам все общие аргументы (типы) для ObjectSet:

objectSet.GetType().GetGenericArguments().First()
1 голос
/ 25 июля 2010

См. этот пост , который я сделал относительно получения EntitySetName.Для моего репозитория я создаю свойство, которое получает имя набора сущностей для конкретного имени класса, чтобы делать именно то, что вы пытаетесь сделать.

0 голосов
/ 28 августа 2017

Проверено с 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();
}
0 голосов
/ 15 января 2014

var objContext = ((IObjectContextAdapter)this.context).ObjectContext;

var objSet = objContext.CreateObjectSet<T>();

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

Object foundEntity;

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<T> entry = this.context.Entry(this.dbset.Find(entityKey.EntityKeyValues.FirstOrDefault().Value));
                        entry.CurrentValues.SetValues(entityToUpdate);
   }
}

this.context.SaveChanges();
0 голосов
/ 25 января 2012

Мне было трудно пытаться сделать почти то же самое, получая имя и значение первичного ключа во время выполнения, когда тип неизвестен.Я просто пытался реализовать схему аудита удалений, и каждое решение, которое я нахожу, включает в себя лишний код, который я действительно не понимаю.EntityKey недоступен из DbContext, что также сбивает с толку и раздражает.Последние 5 строк могут сэкономить вам 5 часов и 1 год облысения.Я не пытаюсь сделать это для вставок, поэтому, если вы это сделаете, вам нужно тщательно проверить эти значения, так как они могут быть 0 или нулем.

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;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...