【发布时间】:2015-11-12 14:35:17
【问题描述】:
我有一个 .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
data 只是用一个条件查询一个表,并按预期返回结果。一切都很好。
但是,在 data1 中,它在技术上也准确地返回了我想要的最终结果,但是我也有一个原始 SQL 记录器来查看幕后发生的事情以及它正在做的事情是使用 select * 等效语句分别查询 ads 表和 Resorts 表,然后当结果从两个表返回时,它在内存中应用连接并在通过 where 子句过滤后返回结果。所以基本上它扫描了大约 100000 行,即使我有 join 和 where 子句,最后它返回一个广告 id 为 413 的单行。
需要注意的一点是,我在为返回 IEnumerable 的 data1 执行连接时调用了存储库类的 Query 方法。我无法将其更改为 IQueryable,因为随后引发了异常,其中包含一些消息,例如 linq 查询引用了不同的上下文。
任何人都可以指导我修改此代码,以便我可以在存储库之间应用真正的 sql 连接,或者是否有办法通过添加中间层作为桥梁来修改此代码。从这一点开始,我需要一些东西。我一直在到处寻找,但无济于事。我敢肯定,我不是这个世界上第一个遇到这个问题的人。肯定会有其他人遇到类似问题,并且可能有人找到了真正的方法。
我的工具和技术如下。
- Visual Studio 2013
- .Net 框架 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;
}
}
【问题讨论】:
标签: c# mysql linq entity-framework-6 repository-pattern