Подтвердить что ты не робот

EntityFramework Получить объект по ID?

Можно ли с помощью Generics получить объект из моей EntityFramework, не зная тип?

Я думаю о чем-то вроде:

public T GetObjectByID<T>(int id)
{
   return (from i in myDatabase.T where i.ID == id select i);
}

Это выполнимо? Могу ли я использовать Reflection, чтобы как-то взять T.GetType().Name и использовать его для таблицы?

ИЗМЕНИТЬ
Еще одно зависание - это то, что не все доступные мне таблицы используют "ID" в качестве уникального имени столбца.

4b9b3361

Ответ 1

Наконец, решила проблему с этим:
http://pastebin.com/kjXUKBNS

Чтобы вызвать код, я использую это:

// Get the id of the object we are saving
PropertyInfo prop = GetProperty<TEntity>(entity, entity.EntityKey.EntityKeyValues[0].Key);
string entityID = prop.GetValue(entity, null).ToString();

// Get the current version of this object
var originalEntity = GetEntity<TEntity>(PropertyEquals, entityID);

Это делает предположение, что первичный ключ, который вы ищете, является первым в списке Первичных ключей.

Ответ 2

Вы можете определить интерфейс, реализованный всеми вашими объектами:

public interface IEntity
{
    int Id { get; }
}

и метод для извлечения вашего объекта:

public T GetObjectById<T>(int id) where T : class, IEntity
{
    return context.CreateObjectSet<T>().SingleOrDefault(e => e.Id == id);
}

Вы также можете использовать аналогичный подход к тому, который указан в связанном вопросе. Вам просто нужно использовать другой метод для получения вашей сущности:

public virtual T GetByKey<T>(int id) where T : class, IEntity
{
     string containerName = context.DefaultContainerName;
     string setName = context.CreateObjectSet<T>().EntitySet.Name;
     // Build entity key
     var entityKey = new EntityKey(containerName + "." + setName, "Id", id);
     return (TEntity)Context.GetObjectByKey(entityKey);         
}

Разница в том, что первый метод всегда запрашивает базу данных, даже если вы уже загрузили экземпляр в контекст, тогда как второй подход сначала проверяет, загружен ли экземпляр. Метод не настолько эффективен, потому что он снова и снова создает эти имена. Здесь - более общий подход, который может работать с любым типом ключа и именем и здесь - это подход к работе со сложными ключами.

Ни один из этих методов напрямую не работает с наследованием - вы должны предоставить базовый тип, чтобы он работал.

Ответ 3

Я думаю, что метод Find() может выполнять то, что вы ищете (DbSet.Find Method).

var someEntity = dbSet.Find(keyValue);

Ответ 4

Трудно сделать полностью общее решение, потому что Entities может иметь составные ключи, но это будет работать для простого случая с одним ключом.

Ключ должен ограничивать T типом System.Data.Objects.DataClasses.EntityObject, который затем имеет свойство EntityKey (которое представляет первичный ключ).

static T GetById<T>(object id) where T : EntityObject
{
    using (var context = new MyEntities())
    {
        return context.CreateObjectSet<T>()
            .SingleOrDefault(t => t.EntityKey.EntityKeyValues[0].Value == id);
    }
}

Ответ 5

Другой способ получить сущность от id на enitiy framework

public T Get<T>(int id) where T : EntityObject;
{
var ObjectSet = _context.CreateObjectSet<T>();
var PropName = ObjectSet.EntitySet.ElementType.KeyMembers[0].ToString();
return  ObjectSet.Where("it." + PropName + "=" + id).FirstOrDefault();
}

Результат

SELECT TOP (1) 
[Extent1].[CatId] AS [CatId], 
[Extent1].[CatName] AS [CatName], 
[Extent1].[CatType] AS [CatType],  
FROM [dbo].[Categories] AS [Extent1]
WHERE [Extent1].[CatId] = 1

Ответ 6

Я думаю, что это могло бы помочь

public static TEntity Find<TEntity>(this ObjectSet<TEntity> set, object id) where TEntity : EntityObject
    {
      using (var context = new MyObjectContext())
      {
        var entity = set.Context.CreateObjectSet<TEntity>();
        string keyName = entity.FirstOrDefault().EntityKey.EntityKeyValues.FirstOrDefault().Key;

        return entity.Where("it." + keyName + " = " + id).FirstOrDefault();
      }
    }

Ответ 7

Одна вещь, с которой я работал, - это определить интерфейс "KeyComparator":

public interface IHasKeyComparator<TObject> {
   Expression<Func<TObject, bool>> KeyComparator { get; } 
}

И затем вы можете реализовать его на каком-либо объекте даже с помощью многозначного ключа:

public sealed class MultiKeyedObject : IHasKeyComparator<MultiKeyedObject> {
   public int ID1 { get; set; }
   public string ID2 { get; set; }       

   readonly Expression<Func<MultiKeyedObject, bool>> mKeyComparator;

   public Expression<Func<MultiKeyedObject, bool>> KeyComparator {
      get { return mKeyComparator; }
   }

   public MultiKeyedObject() {
      mKeyComparator = other => other.ID1 == ID1 && other.ID2 == ID2;
   }
}

И можно использовать его в общем случае, если вы предоставляете ограничение:

public TObject Refresh<TObject>(TObject pObject)
where TObject : IHasKeyComparator<TObject> {
   return this.Set<TObject>().Single(pObject.KeyComparator);
}

Выполнение этого способа требует, чтобы у вас был экземпляр объекта, хотя, хотя вы можете заполнить пустым ключом значения, а затем использовать его, чтобы вытащить из БД.

Ответ 8

Здесь метод, который я использую для получения объекта Entity по идентификатору.

public TEntity GetByKey<TEntity>(object keyValue) where TEntity : class
    {            
        EntityKey key = GetEntityKey<TEntity>(keyValue);

        object originalItem;
        if (ObjectContext.TryGetObjectByKey(key, out originalItem))
        {
            return (TEntity)originalItem;
        }
        return default(TEntity);
    }

Вы можете найти это более надежное решение, чем некоторые из приведенных выше. Я использовал его как часть общего репозитория во многих проектах. Надеюсь, вам это поможет.