提高服务器应用程序可伸缩性的一种方法是异步运行IO绑定操作(读取文件,套接字,Web请求,数据库请求等).这并不意味着在ThreadPool中运行它们,它只会在执行操作时阻塞线程.正确的方法是使用异步API(BeginRead,BeginGetResponse,BeginExecuteReader等).这个问题在CLR vi C# book中有详细描述.
这是一篇关于Linq to SQL中的异步查询的文章.
是否有任何方法可以异步执行Nhibernate查询?怎么样Linq到NHibernate?
谢谢,安德烈
问题:Nhibernate解析"WHERE IN()"sql中的每个值作为参数,MS SQL服务器不支持足够的参数(超过2000).
我正在使用Nhibernate和Linq来从SQL服务器中检索我的数据,我需要根据已知的ID加载很多实体.
我的代码看起来像这样:
int[] knownIds = GetIDsFromFile();
var loadedEntities = _Repository.GetAll()
.Where(x => knownIds.Contains(x.ID))
.ToList();
Run Code Online (Sandbox Code Playgroud)
哪个给出这样的sql:
SELECT id, name FROM MyTable
WHERE id IN (1 /* @p0 */,2 /* @p1 */,3 /* @p2 */,4 /* @p3 */, 5 /* @p4 */)
Run Code Online (Sandbox Code Playgroud)
如果knownIds中的值太多,那么这段代码将抛出异常,因为NHibernate使用了许多参数.
我认为最好的解决方案是如果我能让NHibernate只为整个"WHERE IN()"使用1个参数,但我不知道如何做到这一点:
SELECT id, name FROM MyTable WHERE id IN (1, 2, 3, 4, 5 /* @p0 */)
Run Code Online (Sandbox Code Playgroud)
我很高兴听到有关如何解决这个问题的任何想法 - 通过扩展LINQ提供程序或通过其他方式.一个解决方案是简单地执行查询x次(knownIds.Count/1000),但我更想要一个适用于我所有实体的通用解决方案.
我试图通过搜索谷歌和Stackoverflow来扩展LINQ提供程序,但我找不到解决方案,我没有任何经验与HQL或treebuilder.这里有一些我去过的网站:
更新:
我知道在IN子句中有这么多的值是不好的做法,但我不知道我想要做的更好的解决方案.
考虑一家公司,每个月,所有客户都会为公司的服务付费一次.该公司本身不处理付款,但有另一家公司来收钱.公司每个月都会收到一个包含这些付款状态的文件:如果已付款或未付款.该文件仅包含特定付款的ID,而不包含客户的ID.一家拥有3000名月度客户的公司每月将进行3000次LogPayments,其状态需要更新.1年后将会有大约36,000个LogPayments,所以加载它们似乎也不是一个好的解决方案.
我的解决方案: …
使用FNH,我尝试使用以下方法检索类别:
_session.QueryOver<Data.Model.Category>()
.Where(c => tourCreateRequest.Categories.Contains(c.CategoryId))
.List()
.Select(_categoryMapper.CreateCategory)
.ToList();
Run Code Online (Sandbox Code Playgroud)
但是我在.Contains()方法中遇到错误:
无法识别的方法调用:System.Collections.Generic.ICollection`1 [[System.Int64,mscorlib,Version = 4.0.0.0,Culture = neutral,PublicKeyToken = b77a5c561934e089]]:Boolean包含(Int64)
为什么我得到那个错误,出了什么问题?
我浏览了一些帖子,然后将查询更改为(下面),这适用于Query <>.
_session.Query<Data.Model.Category>()
.Where(c => tourCreateRequest.Categories.Contains(c.CategoryId))
.ToList()
.Select(_categoryMapper.CreateCategory)
.ToList();
Run Code Online (Sandbox Code Playgroud)
我认为QueryOver <>是最新的和最好的,应该使用而不是Query <>.
我使用如上所示的QueryOver <>的方式有什么问题?
我想在编写Linq查询时使用NHibernate进行分页.做这样的事情很容易:
return session.Query<Payment>()
.OrderByDescending(payment => payment.Created)
.Skip((page - 1)*pageSize)
.Take(pageSize)
.ToArray();
Run Code Online (Sandbox Code Playgroud)
但有了这个,我没有得到任何关于项目总数的信息.如果我只是做一个简单的.Count(),那将生成一个对数据库的新调用.
我发现这个答案通过使用未来来解决它.但它使用Criteria.我怎么能用Linq做到这一点?
我正在使用一个暴露IQueryable<T>这样的通用存储库:
public IQueryable<T> AllEntities
{
get
{
return session.Query<T>();
}
}
Run Code Online (Sandbox Code Playgroud)
我可以像这样查询:
var results =
(from e in repository.AllEntities
where e.SomeProperty == "some value"
select e).ToList();
Run Code Online (Sandbox Code Playgroud)
但是,如果T有父母和祖父母实体并且我想急切地加载它们,我必须这样做:
var results =
(from e in repository.AllEntities
where e.SomeProperty == "some value"
select e)
.Fetch(x => x.Parent)
.ThenFetch(x => x.Grandparent)
.ToList();
Run Code Online (Sandbox Code Playgroud)
这工作,但.Fetch并.ThenFetch都Linq2Nhibernate特定扩展方法,这是造成两个问题:
我必须using NHibernate.Linq;在我的文件顶部包含一个声明.但是,在我正在进行此查询时,它应该是与实现无关的.
当我尝试对此进行单元测试时,.Fetch和我的模拟存储库提供的.ThenFetch方法相比,和方法失败IQueryable<T>了.
如何将这些内容包装在我的IRepository<T>界面内或某些通用扩展方法中?
更新:
到目前为止,我所提出的是将其添加到我的存储库界面:
IQueryable<T> EagerLoadParent<U>(IQueryable<T> query,
Expression<Func<T, U>> parentExpression);
IQueryable<T> …Run Code Online (Sandbox Code Playgroud) 我有这样的查询
var orderedQueryable = this.participationRequests
.Fetch(x => x.CommunityEvent)
.Fetch(x => x.CommunityMember)
.ThenFetch(x => x.User)
.Where(x => x.CommunityMember.Community.Id == communityId)
.OrderBy(x => x.CreateDate);
Run Code Online (Sandbox Code Playgroud)
由于此错误,where子句需要在获取之后.问题是thouse Fetch调用发出额外的连接.在SQL查询中,如下所示:
select *
from ParticipationRequests participat0_
left outer join CommunityEvents communitye1_
on participat0_.CommunityEventId = communitye1_.Id
left outer join CommunityMembers communitym2_
on participat0_.CommunityMemberId = communitym2_.Id
left outer join Users user3_
on communitym2_.UserId = user3_.Id
inner join CommunityMembers communitym4_
on participat0_.CommunityMemberId = communitym4_.Id
inner join CommunityMembers communitym5_
on participat0_.CommunityMemberId = communitym5_.Id
inner join Communities community6_
on …Run Code Online (Sandbox Code Playgroud) 我有一个实体及其映射:
public class Test
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual string Description { get; set; }
}
public class TestMap : EntityMap<Test>
{
public TestMap()
{
Id(x => x.Id);
Map(x => x.Name);
Map(x => x.Description);
}
}
Run Code Online (Sandbox Code Playgroud)
我正在尝试对它运行查询(将其从数据库中取出):
var keyword = "test" // this is coming in from the user
keyword = keyword.ToLower(); // convert it to all lower-case
var results = session.Linq<Test>
.Where(x => x.Name.ToLower().Contains(keyword));
results.Count(); …Run Code Online (Sandbox Code Playgroud) 我有一个简单的测试,运行查询5000次.查询的linq版本占用HQL的3倍,缓存的Linq版本比HQL的缓存版本慢得多
HQL:
session.CreateQuery(String.Format("from Episode where SeriesId='{0}' and SeasonNumber='{1}' and EpisodeNumber='{2}'", seriesId, seasonNumber, episodeNumber))
.SetMaxResults(1)
.SetCacheable(true)
.UniqueResult<Episode>();
Run Code Online (Sandbox Code Playgroud)
LINQ:
session.Query<Episode>()
.Where(c => c.SeriesId == seriesId && c.SeasonNumber == seasonNumber && c.EpisodeNumber == episodeNumber)
.Cacheable()
.FirstOrDefault();
Run Code Online (Sandbox Code Playgroud)
结果如下
HQL: Cached: less than a second No-Cache: 5 seconds LINQ: Cached: 8 seconds No-Cache: 15 seconds
我只是想确保我遇到了预期的开销,而不是我做错了什么.
如果那个头顶在那里并且我可以做的不多,你能否建议一个中间地带,这将需要更少的字符串,但提供更好的性能?
注意:我在Fluent Nhibernate中的缓存设置
.Cache(c => c.UseQueryCache().UseSecondLevelCache().UseMinimalPuts().ProviderClass<HashtableCacheProvider>())
我正在使用Fluent NHibernate进行ORM.在这样做的过程中,我尝试使用NHibernate LINQ语法以LINQ的强大功能获取一组数据.我已经正常工作并执行的代码,例外情况是,如果运行时间超过大约30秒,则会引发超时.我的问题是如何通过NHibernate扩展LINQ语句的默认30秒超时?
我已经在这里,这里和这里看过帖子,但前两个是指设置DataContext的Timeout属性,这里不适用,第三个是指用XML设置超时,这也不适用因为我正在使用流畅的NHibernate可以动态生成XML.不仅如此,这篇文章还有2年历史,而Fluent NHibernate自此改变了.
使用ICriteria对象甚至是HQL,我可以指定超时,但这不是目标.我想知道如何设置相同的超时并使用LINQ.
示例代码:
using (var session = SessionFactory.OpenSession())
using (var transaction = session.BeginTransaction())
{
var query = (from mem in session.Query<Member>()
select mem);
query = query.Where({where statement});
int start = (currentPage - 1) * max);
if (start > 0)
query = query.Skip(start).Take(max);
else
query = query.Take(max);
var list = query.ToList();
transaction.Commit();
return list;
}
Run Code Online (Sandbox Code Playgroud)
此代码(where语句无关紧要)适用于所有目的,除非发生超时.
任何帮助表示赞赏.提前致谢!
我有两个类(Request&RequestDetail).我需要Linq To NHibernate通过join在两个类之间进行查询.
var q = SessionInstance.Query<Request>()
.Where(x => x.State == "Init");
var q2 = SessionInstance.Query<RequestDetail>();
q2 = q2.Where(xx => xx.Purpose.Contains("Purpose Sample")); // This line has a error When execution ??`q.ToList()?`
q = q.Join(q2, request => request.Id, detail => detail.Id, (request, detail) => request);
return q.ToList();
Run Code Online (Sandbox Code Playgroud)
当我添加Where条件时q2,Result有一个运行时错误.异常消息是:Specified method is not supported.
堆栈跟踪 :
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.ASTQueryTranslatorFactory.CreateQueryTranslators(IASTNode ast, String queryIdentifier, String collectionRole, Boolean shallow, IDictionary`2 filters, ISessionFactoryImplementor …Run Code Online (Sandbox Code Playgroud)