企业库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; }
}

企业库5.0是否缓存访问器方法的数据读取器和自定义类之间的映射

从代码中,该方法通过:

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();
        }
    }
}