我正在尝试使用NHibernate 3 alpha 1热切地加载所有集合.我想知道这是否正确使用ThenFetch()?
具有多个名称的属性是集合.其他只是一个对象.
IQueryable<T> milestoneInstances = Db.Find<T, IQueryable<T>>(db =>
from mi in db
where mi.RunDate == runDate
select mi).Fetch(mi => mi.Milestone)
.ThenFetch(m => m.PrimaryOwners)
.Fetch(mi => mi.Milestone)
.ThenFetch(m => m.SecondaryOwners)
.Fetch(mi => mi.Milestone)
.ThenFetch(m => m.Predecessors)
.Fetch(mi => mi.Milestone)
.ThenFetch(m => m.Function)
.Fetch(mi => mi.Milestone)
.ThenFetchMany(m => m.Jobs)
.ThenFetch(j => j.Source)
;
Run Code Online (Sandbox Code Playgroud)
我想在NHibernate论坛上问这个问题,但不幸的是,我禁止访问google群组.我知道Fabio在这里,所以也许来自NHibernate团队的人可以对此有所了解吗?谢谢
我们的应用程序具有故事的概念和标签的概念.故事可以应用许多标签,标签可以应用于许多故事,使关系多对多.这两个表,故事和标签与第三个StoriesToTags桥接.
映射文件的相关部分如下:
这是从Story到Tag的映射:
<class name="Story" table="Stories">
...
<set fetch="subselect" name="Tags" table="StoriesToTags">
<key>
<column name="StoryId" />
</key>
<many-to-many class="Tag">
<column name="TagId" />
</many-to-many>
</set>
</class>
Run Code Online (Sandbox Code Playgroud)
以及从Tag到Story的反向关系:
<class name="Tag" table="Tags">
...
<set fetch="subselect" inverse="true" name="Stories" table="StoriesToTags">
<key>
<column name="TagId" />
</key>
<many-to-many class="Story">
<column name="StoryId" />
</many-to-many>
</set>
</class>
Run Code Online (Sandbox Code Playgroud)
如您所见,我们使用子选择提取策略来避免N + 1查询问题.一切都很好,直到您尝试使用LINQ分页结果:
IQueryable<Story> stories = GetStories(...).TakePage(pageNumber, pageSize);
Run Code Online (Sandbox Code Playgroud)
运行此查询后,NHibernate将删除未在查询中加载的所有故事的关系(StoriesToTags中的记录).它似乎只在标记被特定加载时发生(即,触发子选择).如果我们切换到连接或 …
我需要帮助在NHibernate 3 trunk版本中使用Linq进行急切加载.
我有这样的多对多关系:
public class Post
{
public int Id {get;set;}
public IList<Tag> Tags { get;set;}
.
.
.
}
Run Code Online (Sandbox Code Playgroud)
现在我在Fluent NHibernate中有以下映射
public class PostMap:ClassMap<Post>
{
public PostMap()
{
Table("Posts");
Id(x => x.Id);
.
.
HasManyToMany(x => x.Tags)
.Table("PostsTags")
.ParentKeyColumn("PostId")
.ChildKeyColumn("TagId")
.Not.LazyLoad(); // this is not working..
}
}
Run Code Online (Sandbox Code Playgroud)
现在,在获取帖子时,我还需要标签来加载.我知道有可能使用Criteria API和HQL,而SetFetchMode就是我应该使用的.但是在使用Linq时是否有办法使用SetFetchMode?
我正在使用NH3和FNH 1.1重新编译NH3.
我有一个用户模型,我想在加载它时总是检索它的配置文件.我使用NH3的linq提供程序但不能使用它的Fetch方法(因为我的存储库隐藏了NHibernate并返回了IQueryable,并且在查询中调用了ToPagedList,因此阻止我将Fetch作为查询的最后一次调用).
在UserMap我设置:
HasOne(x => x.Profile)
.Not.LazyLoad()
.Cascade.All();
Run Code Online (Sandbox Code Playgroud)
但是将LazyLoad设置为OFF并没有帮助.我也玩过fetch模式.
我的期望是,如果我定义这个映射,那么我甚至不必告诉Linq我要在请求User实体时获取Profile.Linq应该尊重映射,不是吗?
我有一个应用程序,它使用一些数据仓库原则,如维度建模,在一个相当简单的数据库上进行报告.
名为Call的示例(简化)实体如下所示:
public virtual long Id { get; set; }
public virtual string OriginatorNumber { get; set; }
public virtual string DestinationNumber { get; set; }
public virtual DateDimension DateDimension { get; set; }
Run Code Online (Sandbox Code Playgroud)
实际模型的一些属性已被删除,因为它们无关紧要.简化的DateDimension如下所示:
public virtual long Id { get; set; }
public virtual DateTime Date { get; set; }
public virtual int DayOfMonth { get; set; }
public virtual int Weekday { get; set; }
Run Code Online (Sandbox Code Playgroud)
还有很多这样的专栏 - 它们通过应用程序设置预先填充了当前十年.因此,整个十年中的每个日期在此表中都有一行,每个调用都有一个指向它发生日期的链接.这全部映射在Fluent NHibernate并且工作正常.
如果我想做一些报告,我可以使用3.0中改进的NHibernate LINQ提供程序轻松完成.我们希望使用LINQ来提高我们提供的可维护性,但如果我们真的必须,我们将考虑HQL,ICriteria甚至纯SQL.
所以说我想建立一个报告,显示来自某个数字的呼叫数量除以它们发生的星期几.我可以这样轻松地做到这一点:
var query = Calls
.Where(c => …Run Code Online (Sandbox Code Playgroud) 我有NHibernate的问题,我似乎无法找到任何解决方案.在我的项目中,我有一个简单的实体(批处理),但每当我尝试运行以下测试时,我都会遇到异常.我已经尝试了几种不同的方法来执行类似的查询,但几乎所有的异常(它与执行的LINQ方法不同).
第一次测试:
[Test]
public void QueryLatestBatch()
{
using (var session = SessionManager.OpenSession())
{
var batch = session.Query<Batch>()
.FirstOrDefault();
Assert.That(batch, Is.Not.Null);
}
}
Run Code Online (Sandbox Code Playgroud)
例外:
System.NullReferenceException : Object reference not set to an instance of an object.
at NHibernate.Linq.NhQueryProvider.PrepareQuery(Expression expression, ref IQuery query, ref NhLinqExpression nhQuery)
at NHibernate.Linq.NhQueryProvider.Execute(Expression expression)
at System.Linq.Queryable.FirstOrDefault(IQueryable`1 source)
Run Code Online (Sandbox Code Playgroud)
第二个测试:
[Test]
public void QueryLatestBatch2()
{
using (var session = SessionManager.OpenSession())
{
var batch = session.Query<Batch>()
.OrderBy(x => x.Executed)
.Take(1)
.SingleOrDefault();
Assert.That(batch, Is.Not.Null);
}
}
Run Code Online (Sandbox Code Playgroud)
例外:
System.NullReferenceException : Object reference …Run Code Online (Sandbox Code Playgroud) nhibernate castle-windsor linq-to-nhibernate oracle11g windsor-nhfacility
理论上我有两个类似的查询返回相同的结果:
var requestNotWorking = SessionManagement.Db.Linq<Item>(false).Where(i =>
i.Group != null && i.Group.Id == methodParameter)
.ToList();
Run Code Online (Sandbox Code Playgroud)
此请求返回0项,即使它应该返回一项.以下是对后者的重写,但是调用了该ToList()方法.此请求有效并返回第一个查询中预期的项目!
var requestWorking = SessionManagement.Db.Linq<Item>(false).ToList().Where(i =>
i.Group != null && i.Group.Id == methodParameter).ToList();
Run Code Online (Sandbox Code Playgroud)
注意:SessionManagement.Db.Linq<Item>(false)是一个通用的Linq到Nhibernate方法,其布尔属性确定请求是否必须在缓存(true)或数据库(false)中执行.这种方法应该没有错,因为它在解决方案的许多其他部分正常工作.Item的映射没什么特别之处:没有包包和以下参数:
lazy="false" schema="dbo" mutable="false" polymorphism="explicit"
为什么会这样?
编辑:
生成的requestNoWorking的sql请求以:
(Item.Group_ID is not null) and Item.Group_ID=@p0',N'@p0 int',@p0=11768
生成的requestWorking的sql请求大致是一个 select * from dbo.Items
我在asp.net mvc Grid(具体是telerik)上使用LINQ到NHibernate的IQueryable实现,我知道我需要为这个特定的网格急切地获取一些东西.
所以我的查询看起来像这样:
var query = from s in repository.Query<MyClass>()
orderby s.Property.Name, s.Name
select s;
query = query.Fetch(x => x.Property);
Run Code Online (Sandbox Code Playgroud)
现在,如果我执行query.ToList(),一切都很好,我可以验证它在集成测试中是否有效.
这很棒.
但是,如果我执行query.Count()或其他聚合查询的东西,我会得到一个异常:
查询指定的连接提取,但是提取的关联的所有者在选择列表中不存在[FromElement {显式,不是集合连接,获取连接,获取非延迟属性,classAlias = 0,role =,tableName = [Property] ,tableAlias = property1,origin = MyClass myclass0_,colums = {myclass0_.PropertyGuid,className = Property}}] [.Count(.Fetch(.ThenBy(.OrderBy(NHibernate.Linq.NhQueryable`1 [MyClass],Quote(( s,)=>(s.Property.Name)),),Quote((s,)=>(s.Name)),),Quote((x,)=>(x.Property)),), )]
我知道它试图告诉我,我不能急于获取Property,因为MyClass不在select中,但问题是Count()实际上是通过Grid调用的,并且从我的代码外部处理.
我应该做的就是给网格一个IQueryable,它应该能够自己处理分页,排序等.
还有其他人不得不用NHibernate Fetching解决这个问题,你是如何解决它的?
使用OR映射器是否有意义?
我把这个问题放在堆栈溢出处,因为这是我所知道的最好的地方,可以找到愿意提供帮助和意见的智能开发人员.
我的推理如下:
1.)SQL在哪里?
a.)在我参与的每个专业项目中,数据的安全性是关键要求.存储过程为控制访问和审计提供了一个自然的网关.
b.)生产中的应用程序问题通常可以在表和存储过程之间解决,而无需推出新的构建.
2.)如何控制生成的SQL?我信任解析树以生成有效的SQL.我在SQL-Server和Oracle中优化SQL方面有相当多的经验,但如果我再也不必这样做,就不会感到受骗.:)
3.)如果我从存储过程中获取数据,使用OR-Mapper有什么意义?
我已将存储库模式与本地通用数据访问层一起使用.如果需要缓存集合,我会缓存它.我也有在小型CRUD应用程序上使用EF的经验,并且有助于调整遇到性能问题的NHibernate应用程序.所以我有点偏颇,但愿意学习.
在过去的几年里,我们都听到很多受人尊敬的开发人员提倡使用特定的OR-Mappers(实体框架,NHibernate等......).
任何人都可以告诉我为什么有人应该转向ORM主流项目的主流开发?
编辑:http://www.codinghorror.com/blog/2006/06/object-relational-mapping-is-the-vietnam-of-computer-science.html似乎对这个话题进行了强有力的讨论,但它已经出来了约会
另一个编辑:每个人似乎都同意存储过程将用于重型企业应用程序,因为它们具有性能优势,并且能够将编程逻辑添加到数据附近.
我看到支持OR映射器的最有力论据是开发人员的工作效率.
我怀疑ORM运动的一个重要推动因素是开发人员对剩余持久性不可知的偏好(不关心数据是在内存中[除非缓存]还是在数据库上).
ORM似乎是本地和小型Web应用程序的优秀节省时间.
也许我所看到的最好的建议来自client09:使用ORM设置,但使用存储过程来处理数据库密集型的东西(当ORM看起来不够时,使用AKA).
ToFuture与nhibernate linq一起使用吗?如果是这样,你如何使用它?