所以我已经没想到为什么这么慢了。也许你可以帮忙。 所以我试图通过代码使用nHibernate映射从oracle db做一个简单的get on record。我正在使用nuget的nHibernate verison 3.3.1.4。
这是映射代码:
public class Person
{
public virtual PersonKey Key { get; set; }
public virtual string FirstName { get; set; }
public virtual string LastName { get; set; }
}
public class PersonKey
{
public virtual string PersonId { get; set; }
public override bool Equals(object obj)
{
if (obj == null)
return false;
var t = obj as PersonKey;
if (t == null)
return false;
if (PersonId == t.PersonId)
return true;
return false;
}
public override int GetHashCode()
{
return (PersonId).GetHashCode();
}
}
public class PersonMap : ClassMapping<Person>
{
public PersonMap()
{
Schema("MyDB");
Table("Person");
ComponentAsId(id => id.Key, idMapper => idMapper.Property(p => p.PersonId));
Property(i => i.FirstName);
Property(i => i.LastName);
}
}
以下是创建sessionfactory并检索数据的代码。
var mapper = new ModelMapper();
var cfg = new Configuration();
mapper.AddMappings(Assembly.GetExecutingAssembly().GetExportedTypes());
cfg.DataBaseIntegration(c =>
{
c.ConnectionString = @"User Id=user;Password=password;Data Source=MyDB;";
c.Driver<OracleClientDriver>();
c.Dialect<Oracle10gDialect>();
c.LogSqlInConsole = true;
c.LogFormattedSql = true;
c.AutoCommentSql = true;
});
cfg.AddMapping(mapper.CompileMappingForAllExplicitlyAddedEntities());
var sessionFactory = cfg.BuildSessionFactory();
stopwatch.Stop();
Console.WriteLine("Building session factory: {0}", stopwatch.ElapsedMilliseconds);
stopwatch.Restart();
Person entity = null;
using (var session = sessionFactory.OpenSession())
using(var tx = session.BeginTransaction())
{
entity = (Person) session.Get("Person", new PersonKey(){PersonId = "1"});
tx.Commit();
}
生成的查询如下:
SELECT person0_.PersonId as PersonId0_0_,
person0_.FirstName as FirstName0_0_, person0_.LastName as LastName0_0_,
FROM MyDB.Person person0_
WHERE person0_.PersonId=:p0;
:p0 = '1'
平均需要大约80-100秒才能访问检索到的对象。这包括创建会话。
所以我寻找了一些显而易见的事情:
似乎运行查询并且结果从数据库中快速返回(根据nhprof结果),但可能是查询值的水合作用占用了占用时间的实体。我不知道什么可以扼杀时间!
我的下一步是将nHibernate源附加到解决方案并逐步完成,但工作中的下载访问权限有限(甚至到github!)。那么任何想法呢?
干杯。
更新:所以我在我的项目中获得了nHibernate源代码并逐步完成了它。一切都在顺利进行,直到程序得到这段代码:
for (count = 0; count < maxRows && rs.Read(); count++)
在rs.Read()
上,执行会占用时间,其中rs是oracle datareader。这段代码位于Loader.cs文件中的DoQuery
函数中。
奇怪的是,如果传入的查询是非参数化的动态查询(例如select ... from person where personid = '1'
),则执行快速点亮(~1ms),但如果其参数化(例如select ... from person where personid = :p1
)那么它的速度非常慢。由于我想利用nHibernate的强大功能,我需要使用生成的参数化查询。我仍在试图找出oracle读者的原因
答案 0 :(得分:1)
发现问题和解决方案由Deep Shah撰写here。
基本上,NHibernate中的参数化查询与oracle的microsoft驱动程序是造成瓶颈的原因。
他继续分享两个解决方案:
使用oracle开发的Oracle数据客户端驱动程序替换当前的Microsoft oracle驱动程序。使用新驱动程序运行相同的查询消除了性能bottelneck。为此,您需要在要从中触发查询的计算机上安装Oracle数据访问组件(ODAC)。
当通过NHibernate在查询上设置参数时,在查询VARCHAR列时使用“query.SetAnsiString”而不是“query.SetParameter”。
我已经验证了这两种解决方案,但它们都有效。解决方案一是我使用的那个,因为我使用的是代码映射,我将查询生成留给nHibernate。
答案 1 :(得分:0)
我相信你也可以在你的映射中将数据类型设置为ansi字符串,如本文所述: NHibernate 3 specify sql data type with loquacious syntax