企业库5.0缓存datareader和访问者方法的自定义类之间的映射

时间:2011-12-05 12:56:02

标签: c# .net performance enterprise-library enterprise-library-5

想知道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; }
}

2 个答案:

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