通用实体框架更新程序

时间:2012-04-28 15:44:46

标签: linq entity-framework

我正在尝试编写一些可以传入类的内容(包括新数据,包括主键值)和使用实体框架,使用主键检索实体。所以,我有一个类,包括主键值,但我不一定知道主键(但实体框架确实如此)。

(我后来还需要通常更新实体,但这是一个单独的问题)

在LINQ中有一种简单的方法吗?

2 个答案:

答案 0 :(得分: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));

答案 1 :(得分: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