zoukankan      html  css  js  c++  java
  • 使用EntityFramework中DbSet.Set(Type entityType)方法碰到的问题

    使用的是EntityFramework, Version=6.0.0.0,项目原本直接将EntityFramework的Entity拿到UI使用,后面想使用dto对象将数据库的Entity与前台分离开,中间使用AutoMapper类的工具进行转换,而原本的一些EntityFramework泛型方法却出现问题了,比如有个基类的方法是这样的:

    public abstract class ServiceBase<T> : IServiceBase<T> where T : BaseEntity, new()
        {
            protected DefaultDataContext NewDB()
            {
                return new DefaultDataContext();
            }
    
            public void Add(T entity)
            {
                using (var db = this.NewDB())
                {
                    db.Entry<T>(entity).State = EntityState.Added;
                    db.SaveChanges();
                }
            }
    
            public void Modify(T entity)
            {
                entity.LastUpdatedTime = DateTime.Now;
                using (var db = this.NewDB())
                {
                    db.Entry<T>(entity).State = EntityState.Modified;
                    db.SaveChanges();
                }
            }
    
            public void Delete(string id)
            {
                using (var db = this.NewDB())
                {
                    var entity = new T() { Id = id };
                    db.Entry<T>(entity).State = EntityState.Deleted;
                    db.SaveChanges();
                }
            }
           
    
            public T GetByID(string id)
            {
                using (var db = this.NewDB())
                {
                    return db.Set<T>().AsNoTracking().Where(p => p.Id == id).FirstOrDefault();
                }
            }
    
            public IList<T> GetByQuery(BaseQuery query)
            {
                using (var db = this.NewDB())
                {
                    var pageQuery = db.Set<T>().AsNoTracking().OrderBy(p => p.CreatedTime);
                    query.TotalRecordCount = pageQuery.Count();
                    return pageQuery.Page(query.PageIndex, query.PageSize).ToList();
                }
            }
        }

    原本泛型T直接传入的是EntityFramework的实体,使用起来是没问题的,但是现在由于从接口方面进行的隔离,所以继承的接口泛型就不能是数据库的实体泛型T了,而变成dto的泛型TDto:

    public abstract class ServiceBase<TDto> : IServiceBase<TDto> where TDto : BaseEntity, new()
        {}

    而Entity与Dto的对应关系,已经用列表存储起来,用来初始化AutoMapper映射工具:

    class MapMember
        {
            public MapMember(Type from, Type to, bool isTwoWay = true)
            {
                From = from;
                To = to;
                IsTwoWay = isTwoWay;
            }
    
            public Type From { set; get; }
            public Type To { set; get; }
            public bool IsTwoWay { set; get; }
        }

    按原本的设想,应该直接小改一下原来的代码就可以的,因为EntityFramework的DbContext中,同时提供了DbSet<TEntity> Set<TEntity>() 以及 DbSet Set(Type entityType) ,正常看来,两个方法应该能返回一样的对象进行调用,但是实际使用的时候发现不同了,使用DbSet Set(Type entityType)返回的对象,无法正常调用上述的方法,经过一番搜索,发现两个方法返回的对象存在差异,有看到类似使用.Cast解决方法,虽然编译能过,但是运行的时候会报错。

    后面换了个思路,在已知Type的情况下,如何调用泛型<T>方法,暂时找到了一个解决方法:

            public IList<TDto> GetByQuery(BaseQuery query)
            {
                Type l_entityType = DtoExtensions.GetMapType<TDto>();
                dynamic l_entity = l_entityType.Assembly.CreateInstance(l_entityType.FullName);
    
                using (var db = NewDB())
                {
                    return DbBaseQueryToList(l_entity, db, query);
                }
            }
            private IList<TDto> DbBaseQueryToList<TEntity>(TEntity tEntity, DefaultDbContext db, BaseQuery query) where TEntity : BaseEntity
            {
                var l_pageQuery = new FromDbSet<TEntity>(tEntity, db).m_fromDbSet.AsNoTracking().OrderBy(p=>p.CreatedTime);
                return l_pageQuery.Page(query.PageIndex, query.PageSize).ToList().ToMapList<TDto>();
            }
        public class FromDbSet<T> where T : BaseEntity
        {
            public DbSet<T> m_fromDbSet;
    
            public FromDbSet(T o, DefaultDbContext db)
            {
                if (o.GetType() == typeof(BaseEntity))
                    throw new NotSupportedException("不支持基类");
                m_fromDbSet = db.Set<T>();
            }
        }

    测试运行了一下,终于不会报错了。不过中间多了这么些步骤估计是会影响效率的,目前来说影响不大,而且也可以通过重写的方式覆盖掉泛型方法,所以先就这样了。如果您有更好的解决方式欢迎提出来共同探讨!

  • 相关阅读:
    PHP保留小数的相关方法
    ASP.NET Core MVC 之过滤器(Filter)
    ASP.NET Core MVC 之控制器(Controller)
    ASP.NET Core MVC 之视图组件(View Component)
    ASP.NET Core MVC 之局部视图(Partial Views)
    标签助手(TagHelper)
    ASP.NET Core MVC 之布局(Layout)
    ASP.NET Core MVC 之视图(Views)
    ASP.NET Core MVC 之模型(Model)
    九卷读书:淘宝从小到大的发展 -重读《淘宝技术这十年》
  • 原文地址:https://www.cnblogs.com/PFly/p/6478515.html
Copyright © 2011-2022 走看看