2012-04-28 3 views
0

Я пытаюсь написать что-то, где я могу пройти в классе (который будет включать в себя новые данные, включая значения первичного ключа) и использовать сущность-фреймворк, получить объект с использованием первичного ключа. Итак, у меня есть класс, включая значения первичного ключа, но я не обязательно знаю первичный ключ (но Entity Framework делает).Generic Entity Framework Updater

(я позже нужно затем обновить объект в общем, но это отдельный вопрос)

Есть простой способ сделать это в LINQ?

ответ

0

Как я понимаю, у вас есть объект, который не отслеживается контекстом, и вы хотите использовать EF для запроса эквивалентного объекта в базе данных. (Затем вы хотите обновить базу данных со значениями объекта, но это будет отдельный вопрос.)

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

Прежде всего, давайте получим имена первичных ключей для заданного типа. Это сложный бит. Она требует опускаясь до ObjectContext и используя MetadataWorkspace:

public static IEnumerable<string> PrimayKeysFor(
     this DbContext context, 
     object entity) 
    { 
     Contract.Requires(context != null); 
     Contract.Requires(entity != null); 

     return context.PrimayKeysFor(entity.GetType()); 
    } 

    public static IEnumerable<string> PrimayKeysFor(
     this DbContext context, 
     Type entityType) 
    { 
     Contract.Requires(context != null); 
     Contract.Requires(entityType != null); 

     var metadataWorkspace = 
      ((IObjectContextAdapter)context).ObjectContext.MetadataWorkspace; 
     var objectItemCollection = 
      (ObjectItemCollection)metadataWorkspace.GetItemCollection(DataSpace.OSpace); 
     var ospaceTypes = metadataWorkspace.GetItems<EntityType>(DataSpace.OSpace); 

     var ospaceType = ospaceTypes 
      .FirstOrDefault(t => objectItemCollection.GetClrType(t) == entityType); 

     if (ospaceType == null) 
     { 
      throw new ArgumentException(
       string.Format(
        "The type '{0}' is not mapped as an entity type.", 
        entityType.Name), 
       "entityType"); 
     } 

     return ospaceType.KeyMembers.Select(k => k.Name); 
    } 
} 

Теперь мы можем добавить метод расширения, который использует это, чтобы получить ключевые значения для данного объекта (которые не должны быть отслежены):

public static object[] PrimayKeyValuesFor(this DbContext context, object entity) 
    { 
     Contract.Requires(context != null); 
     Contract.Requires(entity != null); 

     var entry = context.Entry(entity); 
     return context.PrimayKeysFor(entity) 
      .Select(k => entry.Property(k).CurrentValue) 
      .ToArray(); 
    } 

Как только у нас это, это довольно легко использовать, чтобы найти объект в базе данных, соответствующий данному объекту, ничего не зная об объекте. Например:

var databaseOrderLine = 
    context.Set<OrderLine>().Find(context.PrimayKeyValuesFor(orderLine)); 
0

Вы можете использовать общий ContextHelper:

public class ContextHelper<T> : IContextHelper<T> 
{ 
    //Instantiate your own EntityFrameWork DB context here, 
    //Ive called the my EntityFramework Namespace 'EF' and the context is  named 'Reporting' 
    private EF.DataContext DbContext = new EF.DataContext(); 
    public bool Insert<T>(T row) where T : class 
    { 
     try 
     { 
      DbContext.Set<T>().Add(row); 
      DbContext.SaveChanges(); 
      return true; 
     } 
     catch(Exception ex) 
     { 
      return false; 
     } 
    } 
    public bool Update<T>(T row) where T : class 
    { 
     try 
     { 
      DbContext.Set<T>().AddOrUpdate(row); 
      DbContext.SaveChanges(); 
      return true; 
     } 
     catch (Exception ex) 
     { 
      return false; 
     } 
    } 
    public bool Delete<T>(T row) where T : class 
    { 
     return Update(row); //Pass an entity with IsActive = false and call update method 
    } 
    public bool AddRows<T>(T[] rows) where T : class 
    { 
     try 
     { 
      DbContext.Set<T>().AddOrUpdate(rows); 
      return true; 
     } 
     catch (Exception ex) 
     { 
      return false; 
     } 
    } 
} 

и вызвать его с помощью этого:

public void NewEmailRecipient(EF.EmailRecipient recipient) 
     { 
      // logic operation here 

      EntityToDB(recipient); 
     } 
     public void NewReportRecipient(EF.ReportRecipient recipient) 
     { 
      // logic operation here 

      EntityToDB(recipient); 
     } 
     public void UpdateEmailRecipient(EF.EmailRecipient recipient) 
     { 
      // logic operation here 

      UpdateEntity(recipient); 
     } 

     public void UpdateReportRecipient(EF.ReportRecipient recipient) 
     { 
      // logic operation here 

      UpdateEntity(recipient); 
     } 
     // call generic methods to update DB 
     private void EntityToDB<T>(T entity) where T : class 
     { 
      var context = new ContextHelper<T>(); 
      context.Insert(entity); 
     } 

     private void UpdateEntity<T>(T entity) where T : class 
     { 
      var context = new ContextHelper<T>(); 
      context.Update(entity); 
     } 

Я отправил демо-решение здесь

https://github.com/andyf1ynn/EntityFramwork-Generic-Type-DAL

Смежные вопросы