企业库5.0是否缓存访问器方法的数据读取器和自定义类之间的映射
本文关键字:读取 自定义 映射 之间 数据 方法 是否 缓存 访问 企业库 | 更新日期: 2023-09-27 18:16:37
想知道Enterprise Library 5.0的Accessor方法是否缓存了数据阅读器的字段以及自定义类的性能,这样它就不会使用反射在自定义类上查找字段名,并且在将数据阅读器映射到对象时不会在数据阅读器上查找字段名?因为将自定义类字段映射到每个访问/代码块的数据读取器字段是一个非常昂贵的操作
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; }
}
从代码中,该方法通过:
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*)
这是entlib支持团队建议的一个简单而漂亮的hack(您可以在http://entlib.codeplex.com/discussions/281833):查看完整的线程
)randylevy Mon at 11:39 PM不,没有缓存RowMapper。唯一的缓存我知道的数据访问应用程序块是存储过程参数缓存。
如果你使用默认的映射器,那么你可以缓存结果你自己,并传递到ExecuteSqlStringAccessor方法支持IRowMapper和IResultSetMapper重载。
例如:
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 From EntLib again(一个更好的解决方案):
谢谢。也许,它可以在Enterprise Library 6中被提上日程既然这是个好主意?
为了好玩,我稍微改进了这个示例来存储RowMapperCache作为EnterpriseLibraryContainer内部的单例,这样它就可以可以像其他企业库对象一样检索。虽然不是企业库的"原生"类,而是使用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();
}
}
}