• 使用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>();
            }
        }

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

  • 相关阅读:
    appium+python自动化项目实战(一):引入nose和allure框架
    jmeter+WebDriver:启动浏览器进行web自动化
    jmeter强大的扩展插件!!
    jmeter+Fiddler:通过Fiddler抓包生成jmeter脚本
    appium+python自动化测试真机测试时报错“info: [debug] Error: Could not extract PIDs from ps output. PIDS: [], Procs: ["bad pid 'uiautomator'"]”
    Appium+python移动端自动化测试-python库及pycharm安装(二)
    Appium+python移动端自动化测试-环境搭建(一)
    安全测试之bWAPP环境搭建
    Battery Historian之App耗电量测试
    (15)Docker之用Nginx实现SpringBoot应用的负载均衡简单记录
  • 原文地址:https://www.cnblogs.com/PFly/p/6478515.html
Copyright © 2020-2023  润新知