我有一个.Net解决方案,其中的多个项目如下所示。


业务(解决方案文件夹)


核心(项目)
接口(项目)

数据(解决方案文件夹)


数据(项目)

演示文稿(解决方案文件夹)


AdminPanel(项目)

共享(解决方案文件夹)


共同(项目)



我已经使用Unity(即Microsoft.Practices.Unity)在IoC层上实现了通用存储库模式。一切都很好,除非我想执行多表简单或复杂联接。我尝试了许多不同的方法。我在这里遍历了关于存储库中联接的每个现有线程,但是它们都无法满足我的需求。

这是我的存储库类。

public class Repository<TEntity> : IRepository<TEntity> where TEntity : class, IEntity
    {
        protected BuyatimeshareModel Context { get; private set; }

        public Repository(IContextFactory contextFactory)
            : this(contextFactory.Get())
        {
        }

        protected Repository(BuyatimeshareModel context)
        {
            context.Database.Log = message => { Common.Logging.Log(message); };
            Context = context;
        }
        IDbSet<TEntity> DbSet
        {
            get
            {
                return Context.Set<TEntity>();
            }
        }
        public TEntity Add(TEntity instance)
        {
            DbSet.Add(instance);
            Context.SaveChanges();
            return instance;
        }

        public void Remove(TEntity instance)
        {
            DbSet.Remove(instance);
            Context.SaveChanges();
        }
        public TEntity FindOne(Expression<Func<TEntity, bool>> predicate)
        {
            return DbSet.AsQueryable().FirstOrDefault(predicate);
        }

        public IEnumerable<TEntity> All()
        {
            return DbSet.AsQueryable();
        }

        public IEnumerable<TEntity> Query() { IQueryable<TEntity> query = DbSet; return query.ToList(); }

        public IEnumerable<TEntity> FindAll(Expression<Func<TEntity, bool>> predicate)
        {
            return DbSet.AsQueryable().Where(predicate);
        }

        public int Count()
        {
            return DbSet.AsQueryable().Count();
        }

        public int Count(Expression<Func<TEntity, bool>> predicate)
        {
            return DbSet.AsQueryable().Count(predicate);
        }

        public bool Exists(Expression<Func<TEntity, bool>> predicate)
        {
            return DbSet.AsQueryable().Any(predicate);
        }
    }


这是我的IoC层。

public class UnityControllerFactory : DefaultControllerFactory
    {
        IUnityContainer container;

        public UnityControllerFactory(IUnityContainer container)
        {
            this.container = container;
        }

        protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
        {
            try
            {
                if (controllerType == null)
                    throw new ArgumentNullException("controllerType");

                if (!typeof(IController).IsAssignableFrom(controllerType))
                    throw new ArgumentException(string.Format(
                        "Type requested is not a controller: {0}", controllerType.Name),
                        "controllerType");

                return container.Resolve(controllerType) as IController;
            }
            catch { return null; }
        }

        public static void Configure()
        {
            IUnityContainer container = new UnityContainer();
            /*string connectionString = ConfigurationManager.ConnectionStrings["Connection"].ConnectionString;*/
            container.RegisterType<IContextFactory, ContextFactory>(new ContainerControlledLifetimeManager())//, new InjectionConstructor(connectionString))
                     .RegisterType<IUnitOfWork, UnitOfWork>(new ContainerControlledLifetimeManager())
                     .RegisterType<IAdminService, AdminService>()

                     .RegisterType(typeof(IRepository<>), typeof(Repository<>));
            ControllerBuilder.Current.SetControllerFactory(new UnityControllerFactory(container));
        }
    }


最后,这是我的服务层,我正在其中尝试从存储库层查询一些数据。

public class AdminService : IAdminService
    {
        private readonly IRepository<press_releases> pressReleasesRepo;
        private readonly IRepository<tblads> adsRepo;
        private readonly IRepository<tblresorts> resortsRepo;

        public AdminService(IRepository<press_releases> _pressReleasesRepo, IRepository<tblads> _adsRepo, IRepository<tblresorts> _resortsRepo)
        {
            pressReleasesRepo = _pressReleasesRepo;
            adsRepo = _adsRepo;
            resortsRepo = _resortsRepo;
        }
        public List<press_releases> Test()
        {
            var data = pressReleasesRepo.FindAll(p => p.pr_id > 0);
            var data1 =
                (from a in adsRepo.Query()
                    join r in resortsRepo.Query() on a.resort_id equals r.resort_id
                    where a.ad_id == 413
                    select new
                    {
                        OwnerId = a.owner_id,
                        ResortName = r.name,
                        AdId = a.ad_id,
                        AskingPrice = a.askingPriceInt
                    }).ToList();

            var model = data.ToList();
            return model;
        }
    }


现在,这里有两个查询。数据和数据1

数据只是用一个条件查询一个表,并按预期返回结果。这里一切都很好。

但是,在data1中,从技术上来说,它也恰好返回了我想要的最终结果,但我也准备了一个原始SQL记录器,以了解幕后发生的情况,以及它的用途是分别查询ads表和resorts表选择*等价的语句,然后当结果从两个表中返回时,它将在内存中应用联接,并在通过where子句过滤后返回结果。因此,即使我已经加入join和where子句,最后它仍然扫描了大约100000行,最后返回了一行广告ID为413的行。

需要注意的一件事是,我在执行data1的联接时正在调用存储库类的Query方法,该联接返回IEnumerable。我无法将其更改为IQueryable,因为随后引发了异常,例如linq查询具有对不同上下文的引用。

任何人都可以指导我修改此代码,以便我可以在存储库之间应用真正的sql联接,或者是否可以通过添加中间层作为桥梁来修改此代码。从这一点上我需要前进。我一直到处寻找,但无济于事。我确定我不是这个世界上第一个可能遇到此问题的人。肯定会有其他人有类似的问题,并且可能是找到真正方法的人。

我的工具和技术如下。


Visual Studio 2013
.Net Framework 4.0
MySQL数据库
适用于Visual Studio 1.2.4的MySQL
MySQL连接器6.9.6
实体框架6
Windows 10专业版x64


如果有什么我想念的,请告诉我。

任何帮助将不胜感激。

编辑:

这是ContextFactory类

public class ContextFactory : IContextFactory
    {
        private bool _isDisposed;
        private SomeModel _context;

        public ContextFactory()
        { }

        public SomeModel Get()
        {
            _context = new SomeModel();
            return _context;
        }

        ~ContextFactory()
        {
            Dispose(false);
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (!_isDisposed && disposing && (_context != null))
                _context.Dispose();

            _isDisposed = true;
        }
    }

最佳答案

这是您在data1中使用的存储库中的方法。

public IEnumerable<TEntity> Query() { IQueryable<TEntity> query = DbSet; return query.ToList(); }


每当您点击“ .ToList()”时,它都会进入数据库。

如果要先创建查询然后执行,请使用存储库的'DbSet'属性。

关于c# - 在C#中使用通用存储库时联接多个表,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/32093041/

10-12 17:32
查看更多