想知道Enterprise Library 5.0的Accessor方法是否缓存datareader的字段以及性能的自定义类,以便它不会使用反射在自定义类上查找字段名称,并且在查找时不会在datareader上查找字段名称。将datareader映射到对象?因为将自定义类字段映射到每个访问/代码块的datareader字段是一项非常昂贵的操作
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Database db = EnterpriseLibraryContainer.Current.GetInstance<Database>();
var r = db.ExecuteSqlStringAccessor<Region>("SELECT * FROM Region");
}
}
public class Region
{
public string RegionnId { get; set; }
public string Name { get; set; }
}
答案 0 :(得分:5)
从the code开始,该方法通过:
public static IEnumerable<TResult> ExecuteSqlStringAccessor<TResult>(this Database database, string sqlString)
where TResult : new()
{
return CreateSqlStringAccessor<TResult>(database, sqlString).Execute();
}
然后到
IRowMapper<TResult> defaultRowMapper = MapBuilder<TResult>.BuildAllProperties();
通过
return MapAllProperties().Build();
是:
public static IMapBuilderContext<TResult> MapAllProperties()
{
IMapBuilderContext<TResult> context = new MapBuilderContext();
var properties =
from property in typeof(TResult).GetProperties(BindingFlags.Instance | BindingFlags.Public)
where IsAutoMappableProperty(property)
select property;
foreach (var property in properties)
{
context = context.MapByName(property);
}
return context;
}
所以没有;我看不到任何缓存的证据。你可以添加一些,或者你可以使用已经完成物化器和参数化缓存的内容(* cough * dapper-dot-net * cough *)
答案 1 :(得分:2)
这是entlib支持团队建议的一个简单而好的黑客(您可以查看http://entlib.codeplex.com/discussions/281833处的完整主题):
randylevy周一晚上11点39分不,没有任何缓存 RowMapper的。我唯一知道的数据访问缓存 Application Block是存储过程参数缓存。
如果您使用默认映射器,则可以缓存结果 自己并传递到ExecuteSqlStringAccessor方法,因为它 支持IRowMapper和IResultSetMapper重载。
E.g:
public class RowMapperCache
{
private Dictionary<Type, object> cache = new Dictionary<Type, object>();
private object locker = new object();
public IRowMapper<T> GetCachedMapper<T>() where T : new()
{
Type type = typeof(T);
lock (locker)
{
if (!Contains(type))
{
cache[type] = MapBuilder<T>.BuildAllProperties();
}
}
return cache[type] as IRowMapper<T>;
}
private bool Contains(T type)
{
return cache.ContainsKey(type);
}
}
// retrieve default mapper and cache it
IRowMapper<Region> regionMapper = rowMapperCache.GetCachedMapper<Region>();
var db = EnterpriseLibraryContainer.Current.GetInstance<Database>();
var r = db.ExecuteSqlStringAccessor<Region>("SELECT * FROM Region", regionMapper);
UPDATE 再次从EntLib(更好的解决方案):
感谢。也许,它可以放在企业库6的桌面上 因为这似乎是一个好主意?
为了好玩,我稍微改进了一些例子来存储RowMapperCache 作为EnterpriseLibraryContainer内部的单例,以便它可以 与其他Enterprise Library对象类似地检索。虽然 不是企业图书馆&#34; native&#34; class,使用RowMapperCache 只有使用企业库,所以它不是一个巨大的飞跃存储它 容器(特别是如果你没有使用完整的Unity IoC)。
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ContainerModel;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ContainerModel.Unity;
using Microsoft.Practices.EnterpriseLibrary.Data;
using Microsoft.Practices.ServiceLocation;
using Microsoft.Practices.Unity;
namespace RowMapperConsole
{
public class Region {}
public class RowMapperCache
{
private Dictionary<Type, object> cache = new Dictionary<Type, object>();
private object locker = new object();
public IRowMapper<T> GetCachedMapper<T>() where T : new()
{
Type type = typeof(T);
lock (locker)
{
if (!Contains(type))
{
cache[type] = MapBuilder<T>.BuildAllProperties();
}
}
return cache[type] as IRowMapper<T>;
}
private bool Contains(T type)
{
return cache.ContainsKey(type);
}
}
class Program
{
static void Main(string[] args)
{
ApplicationInitialize();
// ...
IEnumerable<Region> regions = GetRegions();
}
public static void ApplicationInitialize()
{
ConfigureContainer(container =>
{
// Register as Singleton
container.RegisterType<RowMapperCache>(new ContainerControlledLifetimeManager());
});
}
public static void ConfigureContainer(Action<IUnityContainer> action)
{
IUnityContainer container = new UnityContainer();
if (action != null)
action(container);
IContainerConfigurator configurator = new UnityContainerConfigurator(container);
EnterpriseLibraryContainer.ConfigureContainer(configurator, ConfigurationSourceFactory.Create());
IServiceLocator locator = new UnityServiceLocator(container);
EnterpriseLibraryContainer.Current = locator;
}
public static IEnumerable<Region> GetRegions()
{
IRowMapper<Region> regionMapper = EnterpriseLibraryContainer.Current.GetInstance<RowMapperCache>()
.GetCachedMapper<Region>();
var db = EnterpriseLibraryContainer.Current.GetInstance<Database>();
return db.ExecuteSqlStringAccessor<Region>("SELECT * FROM Region", regionMapper).ToList();
}
}
}