如何创建通用EF插入方法? [英] How to create generic EF Insert method?

查看:250
本文介绍了如何创建通用EF插入方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建一个通用的C#类,它将使用Entity Framework向数据库添加一行。

I'd like to create a generic C# class with a method that will add a row to a database using Entity Framework.

我有一个表地址。我写了以下代码来添加一个地址到数据库:

I have one table called Address. I've written the following code to add an address to the database:

public class AddressExchange
{
    public int Insert(Address address)
    {
        using (var db = new DemoWebEntities())
        {
            //db.AddObject("Address", address);
            db.Addresses.AddObject(address);
            db.SaveChanges();
            return address.Id;
        }
    }
}

我想写一个将为我的EDMX中的任何实体执行此操作的通用类。我认为它应该是这样的:

I would like to write a generic class that will perform this operation for any entity in my EDMX. I think that it should look something like this:

public class EntityExchange<T, KeyType>
{
    public KeyType Insert(T t)
    {
        using (var db = new DemoWebEntities())
        {
            // The entity set name might be wrong.
            db.AddObject(typeof(T).Name, t);                

            // EF doesn't know what the primary key is.
            return t.Id;
        }
    }
}

我认为这可能是要使用 AddObject 方法将对象添加到数据库,但实体集名称不一定与类型名称相同,特别是如果已经被多重化了!

I think it may be possible to use the AddObject method to add the object to the database, but the entityset name is not necessarily the same as the type name, especially if it has been pluralized!

我还想将主键返回给调用者,但我不知道如何知道哪个字段包含主键。

I also want to return the primary key to the caller, but I don't know how to tell which field contains the primary key.

推荐答案

我在通用存储库中有一个通用的InsertOrUpdate方法,也可以确保代理被创建。 (代理需要支持延迟加载,如果您使用new创建实体,则不会创建代理)。请参阅此处的问题

I have a generic InsertOrUpdate method in a generic repository that also ensures proxies are created. (Proxies are required to support lazy loading and if you create an entity using "new", then proxies are not created). See the question here

public class RepositoryBase<T> : IRepository<T> where T : ModelBase
{
    public virtual T InsertOrUpdate(T e)
    {
        DbSet<T> dbSet = context.Set<T>();

        //Generate a proxy type to support lazy loading
        T instance = dbSet.Create();

        DbEntityEntry<T> entry;
        if (e.GetType().Equals(instance.GetType()))
        {
            //The entity being added is already a proxy type that 
            //supports lazy loading just get the context entry
            entry = context.Entry(e);
        }
        else
        {
            //The entity being added has been created using the "new" operator. 
            //Attach the proxy
            //Need to set the ID before attaching or we get 
            //The property 'ID' is part of the object's key 
            //information and cannot be modified when we call SetValues
            instance.ID = e.ID;
            entry = context.Entry(instance);
            dbSet.Attach(instance);

            //and set it's values to those of the entity
            entry.CurrentValues.SetValues(e);
            e = instance;
        }

        entry.State = e.ID == default(int) ?
                                EntityState.Added :
                                EntityState.Modified;

        return e;
    }
}

public abstract class ModelBase
{
    public int ID { get; set; }
}

请注意,所有模型都继承了ModelBase,以便处理ID问题,返回实体而不仅仅是ID。这可能不是绝对必要的,因为对实体的引用被传入,并且EF对ID执行fixup,所以您可以随时从传入的引用访问它。

Note that all the models inherit ModelBase so that handles the ID issue and I return the entity rather than just the ID. That is probably not strictly necessary since a reference to the entity is passed in and EF performs fixup on the ID anyway so you can always access it from the refernce passed in.

这篇关于如何创建通用EF插入方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆