在过去的几个月里,我一直在使用Linq到NHibernate开发一个webapp,但是直到现在还没有描述它生成的SQL.使用NH Profiler,现在看来,当执行Linq表达式时,下面的代码块会使DB超过3,000次.
var activeCaseList = from c in UserRepository.GetCasesByProjectManagerID(consultantId)
where c.CompletionDate == null
select new { c.PropertyID, c.Reference, c.Property.Address, DaysOld = DateTime.Now.Subtract(c.CreationDate).Days, JobValue = String.Format("£{0:0,0}", c.JobValue), c.CurrentStatus };
Run Code Online (Sandbox Code Playgroud)
存储库方法如下所示:
public IEnumerable<Case> GetCasesByProjectManagerID(int projectManagerId)
{
return from c in Session.Linq<Case>()
where c.ProjectManagerID == projectManagerId
select c;
}
Run Code Online (Sandbox Code Playgroud)
它似乎首先运行初始Repository查询,然后遍历所有结果检查以查看CompletionDate是否为null,但是首先发出查询以获取c.Property.Address.
因此,如果初始查询返回2,000条记录,即使其中只有五条没有CompletionDate,它仍会触发SQL查询以返回2,000条记录的地址详细信息.
我想象的方式可行,是它会评估所有WHERE和SELECT子句并简单地合并它们,因此初始查询将如下:
SELECT ... WHERE ProjectManager = @ p1 AND CompleteDate IS NOT NULL
哪个会产生5个记录,然后它可以触发另外5个查询来获取地址.我在这里期待太多,还是我只是做错了什么?
安东尼
我有简单的情况(如图像链接文本)和简单的SQL查询
SELECT M.Name,
A.Name,
B.Name
FROM Master M LEFT JOIN DetailA A
ON M.DescA = A.Id LEFT JOIN DetailB B
ON M.DescB = B.Id
Run Code Online (Sandbox Code Playgroud)
如何使用CriteriaAPI在nHibernate中实现相同的效果?
我有这样的事情:
public class Employee : ClassBase, IContactData
{
public virtual string FirstName { get; set; }
public virtual string MiddleName { get; set; }
public virtual string LastName { get; set; }
public virtual string NickName { get; set; }
public virtual string Login { get; set; }
public virtual string Password { …Run Code Online (Sandbox Code Playgroud) 我想为我提供以下API MyTypeRepository:
var myChosenInstance = _myRepository.FindOne(x => x.MyProperty == "MyValue");
Run Code Online (Sandbox Code Playgroud)
..以及用于在存储库中构造linq查询的lambda,然后由Linq用于NHibernate.
这可能吗?我的存储库FindOne方法会是什么样的?
您好我有以下代码使用带有linq的nhibernate 3.0从我的数据库中检索数据 -
public IQueryable<myEntity> getEntityWithChild
{
get { return _currentSession.Query<myEntity>().Fetch(c => c.myOtherEntity); }
}
Run Code Online (Sandbox Code Playgroud)
当我尝试将其传递给视图时,我收到以下错误,这不是非常具体.当我没有急于使用以下装载时,这工作正常 -
public IQueryable<myEntity> getEntityWithChild
{
get { return _currentSession.Query<myEntity>(); }
}
Run Code Online (Sandbox Code Playgroud)
但是每次其他实体延迟加载时我都会创建一个单独的查询.有没有人在此之前看到这个可能能指出我正确的方向.谢谢你的任何想法.
System.NotSupportedException was unhandled by user code
Message=Specified method is not supported.
Source=NHibernate
StackTrace:
at NHibernate.Hql.Ast.ANTLR.PolymorphicQuerySourceDetector.GetClassName(IASTNode querySource)
at NHibernate.Hql.Ast.ANTLR.PolymorphicQuerySourceDetector.Process(IASTNode tree)
at NHibernate.Hql.Ast.ANTLR.AstPolymorphicProcessor.Process()
at NHibernate.Hql.Ast.ANTLR.AstPolymorphicProcessor.Process(IASTNode ast, ISessionFactoryImplementor factory)
at NHibernate.Hql.Ast.ANTLR.ASTQueryTranslatorFactory.CreateQueryTranslators(IASTNode ast, String queryIdentifier, String collectionRole, Boolean shallow, IDictionary`2 filters, ISessionFactoryImplementor factory)
at NHibernate.Hql.Ast.ANTLR.ASTQueryTranslatorFactory.CreateQueryTranslators(String queryIdentifier, IQueryExpression queryExpression, String collectionRole, Boolean shallow, IDictionary`2 filters, ISessionFactoryImplementor factory) …Run Code Online (Sandbox Code Playgroud) 我正在努力实现:
select StoreId, StoreName from Store where StoreId in (
select StoreId from Employee where EmployeeName = 'Steve Jobs')
Run Code Online (Sandbox Code Playgroud)
我有这个代码:
public class Store
{
public virtual int StoreId { get; private set; }
public virtual string StoreName { get; set; }
public virtual IList<Employee> Staff { get; set; }
}
public class Employee
{
public virtual Store Store { get; set; }
public virtual int EmployeeId { get; private set; }
public virtual string EmployeeName { get; set; }
} …Run Code Online (Sandbox Code Playgroud) 我知道我在这里做错了,我只是不知道是什么,因为我不太确定问题是什么.这是被称为的代码:
电话
System.Linq.Expressions.Expression<Func<AccountDataModel, bool>> deleg =
(m => m.Email == model.Email);
AccountDataModel query = database.FindBy(deleg);
Run Code Online (Sandbox Code Playgroud)
电话通向哪里
public T FindBy(Expression<Func<T, bool>> expression)
{
return FilterBy(expression).Single();
}
public IQueryable<T> FilterBy(Expression<Func<T, bool>> expression)
{
return All().Where(expression).AsQueryable();
}
public IQueryable<T> All()
{
return (from data in _session.Query<T>()
select data);
}
Run Code Online (Sandbox Code Playgroud)
抛出异常
Sequence contains no elements
Run Code Online (Sandbox Code Playgroud)
泽细节
基本上,我现在正在尝试测试的是我网站上的注册模块,该模块应该搜索已经提供的电子邮件以查看它是否存在.我在数据库中隐藏了一个加密的电子邮件地址(是的,模型中的电子邮件也已加密),这应该与提供的注册电子邮件相匹配.问题是没有返回任何结果.
我到底错在了什么?
我刚遇到了一个非常令人惊讶的问题.
情况很简单:返回当前活动的所有实体,这意味着:GetAll()根据布尔活动属性过滤方法返回的所有结果
public IQueryable<T> GetAllActive()
{
return implementation.GetAll().Where(a => ((IDeactivable)a).Active);
}
Run Code Online (Sandbox Code Playgroud)
其中GetAll()实现对象的方法定义为:
public IQueryable<T> GetAll();
Run Code Online (Sandbox Code Playgroud)
问题是,GetAllActive()返回所有记录,无论其Active属性的值如何,就像没有Where子句一样.
可能是什么原因呢?
注意:代码简化,T检查类型以实现IDeactivable接口.在运行时也不会抛出异常.
编辑:实现对象返回的IQueryable来自NHibernate
Edit2:我使用以下代码检查实体的实际值(除了使用VS Debugger):
foreach (var a in active) { //active -> filtered IQueryable before return
_logger.Warn(a.Id);
_logger.Warn(((IDeactivable)a).Active);
}
Run Code Online (Sandbox Code Playgroud)
结果是:
11/30/2011 18:10:00 WARN xxx.Repository`1.GetAllActive: 70db43fa-2361-4c1f-a8e5-9fab012b5a2b
11/30/2011 18:10:01 WARN xxx.Repository`1.GetAllActive: False
11/30/2011 18:10:02 WARN xxx.Repository`1.GetAllActive: 5493c9bb-ec6e-4690-b5d6-9fab012b5b16
11/30/2011 18:10:02 WARN xxx.Repository`1.GetAllActive: True
Run Code Online (Sandbox Code Playgroud) 我正在使用NHibernate 3.2,我有一个存储库方法,如下所示:
public IEnumerable<MyModel> GetActiveMyModel()
{
return from m in Session.Query<MyModel>()
where m.Active == true
select m;
}
Run Code Online (Sandbox Code Playgroud)
哪个按预期工作.但是,有时当我使用这种方法时,我想进一步过滤它:
var models = MyRepository.GetActiveMyModel();
var filtered = from m in models
where m.ID < 100
select new { m.Name };
Run Code Online (Sandbox Code Playgroud)
其中产生与第一个相同的SQL,第二个过滤器和选择必须在事后完成.我认为LINQ中的重点是它形成了一个表达树,在需要时它被解开,因此可以创建正确的作业SQL,从而节省了我的数据库请求.
如果没有,这意味着我的所有存储库方法都必须准确地返回所需的内容,并且我不能在不受惩罚的情况下进一步使用LINQ.
我弄错了吗?
更新
响应下面的评论:我省略了迭代结果的行,这导致初始SQL运行(WHERE Active = 1),第二个过滤器(ID <100)显然在.NET中完成.
另外,如果我用第二块代码替换
var models = MyRepository.GetActiveMyModel();
var filtered = from m in models
where m.Items.Count > 0
select new { m.Name };
Run Code Online (Sandbox Code Playgroud)
它生成初始SQL以检索活动记录,然后为每条记录运行一个单独的SQL语句,以找出它有多少项,而不是像我期望的那样写一些东西:
SELECT Name
FROM MyModel m
WHERE Active = 1
AND …Run Code Online (Sandbox Code Playgroud) 我正在使用NHibernate 3.0并且正在比较Query和QueryOver
var p = _prepo.Query<Party>()
.Where(c => c.Person.LastName == "Bobby")
.FirstOrDefault();
Run Code Online (Sandbox Code Playgroud)
上面的工作,如果我查看对象图,我得到p.Person的代理类.
var p = _prepo.QueryOver<Party>()
.Where(c => c.Person.LastName == "Bobby")
.FirstOrDefault();
Run Code Online (Sandbox Code Playgroud)
这个失败,错误==>无法解析属性:Person.LastName:
为什么?
嗨:我试过看其他帖子.如果这是一个重复的帖子,我会提前道歉.
sql查询是这样的:
select * from ApiData where BrandID = 'SOUPBRAND' and Culture = 'de-de'
or
( BrandID = 'SOUPBRAND' and Culture = 'pt-br' and EntityType = 'contactus')
or
(BrandID = 'examplefoods')
Run Code Online (Sandbox Code Playgroud)
nhibernate查询会是什么样的?
这是我到目前为止:
var mainQuery = _session.QueryOver<ApiData>();
foreach (var brandPermission in permissions)
{
var query = _session.QueryOver<ApiData>();
if (!string.IsNullOrEmpty(brandPermission.Culture) && !string.IsNullOrEmpty(brandPermission.Publication))
{
query = query.Where(a => (a.Culture == brandPermission.Culture)
&& (a.Publication == brandPermission.Publication)); //FetchEntries(apiUser.DefaultCulture, apiUser.Publication);
}
else if (!string.IsNullOrEmpty(brandPermission.Culture))
{
query = query.Where(a => (a.Culture == brandPermission.Culture)); //FetchEntries(apiUser.DefaultCulture);
}
query …Run Code Online (Sandbox Code Playgroud)