2012-04-28 59 views
0

我想写一些东西,我可以传入一个类(其中将包括新数据,包括主键值),并使用实体框架,使用主键检索实体。所以,我有一个类,包括主键值,但我不一定知道主键(但实体框架)。通用实体框架更新器

(我以后还需要那么一般更新实体,但是这是一个单独的问题)

有一个简单的方法在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(); 
    } 

一旦我们有了它,使用Find可以非常容易地在数据库中获取与给定对象相对应的实体,而无需了解对象的任何信息。例如:

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