在.net实体框架6中以编程方式决定实体类型

时间:2017-09-17 12:19:38

标签: .net entity-framework

我有一个用id更新某个记录的方法,并且有一些实体与该表具有相同的结构,所以我想知道我该如何做以下的事情;

    public void deleteCarwithId(int id, int type)
            {
                string[] brands = { "BMW", "VOLKSWAGEN", "RENAULT", "FIAT" };
                T entity = Convert.ToEntity(brands[type]);//ofc there is no such a method yet
                var result =UnitOfWork.Repository<entity>().FirstOrDefault(u => u.ID == id);
                result.IsDeleted = true;
                Update(result);
            }

而不是这个(它有效但丑陋);

public void deleteCarwithId(int id, int type)
    {
        string[] brands = { "BMW", "VOLKSWAGEN", "RENAULT", "FIAT" };
        if (brands[type] == "BMW")
        {
            var result = UnitOfWork.Repository<BMW>().FirstOrDefault(u => u.ID == id);
            result.IsDeleted = true;
            Update(result);
        }
        if (brands[type] == "VOLKSWAGEN")
        {
            var result = UnitOfWork.Repository<VOLKSWAGEN>().FirstOrDefault(u => u.ID == id);
            result.IsDeleted = true;
            Update(result);
        }
    }

1 个答案:

答案 0 :(得分:1)

实现这一目标的最简单方法是使用反射和MakeGenericMethod函数:

1st:为将来要删除的类型创建一个界面:

public interface IDeletable
{
    bool IsDeleted { get; set; }
    int Id { get; set; }
}

第二个基于创建的接口结构分离逻辑功能

public void Delete<T>(UnitOfWork unitOfWork, int id) where T: IDeletable
{
    var repository = (Repository<T>)typeof(UnitOfWork).GetMethod("Repository")
        .MakeGenericMethod(typeof(T)).Invoke(new UnitOfWork(), new object[0]);
    var item = repository.FirstOrDefault(x => x.Id == id);
    item.IsDeleted = true;
    Update(item);
}

第3次调用指定类型的函数

public void deleteCarwithId(int id, int type)
{
    var method = typeof(Program).GetMethod("Delete"); // Binding parameters could requires
    switch(type)
    {
        case 0: method.MakeGenericMethod(typeof(BMW))
                .Invoke(this, new object[]{unitOfWork, id});
                return;
        ...
    }
}

作为反射的替代方法,可以使用存储库的字典: 假设上面的第一步已经完成并且您的存储库是 IQueryable ,那么该方法可能如下所示:

public void deleteCarwithId(int id, int type)
{
    var source = new Dictionary<int, IQueryable<IDeletable>>
    {
        {0, unitOfWork.Repository<BMW>() }
        // all other types
    };
    var repository = source[i];
    var item = repository.FirstOrDefault(x => x.Id == id);
    item.IsDeleted = true;
    Update(item);
}

当然,为了减少不必要的初始化量,可以将Dictionary创建为托管对象中的字段,甚至可以创建为静态字段。如果是静态字段,GC将从不收集。