выполняет сопоставление кэша Enterprise Library 5.0 между устройством чтения данных и пользовательскими классами для методов доступа - PullRequest
4 голосов
/ 05 декабря 2011

Хотелось бы знать, кэшируют ли методы Accessor Enterprise Library 5.0 поля данных и пользовательские классы для повышения производительности, чтобы он не просматривал имена полей в пользовательских классах с помощью отражений и не просматривал имена полей в хранилище данных при сопоставление хранилища данных с объектами? Потому что это довольно дорогая операция для сопоставления пользовательских полей класса с полями чтения данных для каждого блока доступа / кода

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 ]

5 голосов
/ 05 декабря 2011

С кодом этот метод проходит через:

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

так что нет;Я не вижу доказательств какого-либо кеширования там.Вы можете добавить некоторые, или вы можете использовать купольные устройства, которые уже выполняют кэширование материализатора и параметризации (* кашель * dapper-dot-net * кашель *)

2 голосов
/ 06 декабря 2011

Вот простой и приятный взлом, предложенный службой поддержки entlib (вы можете проверить всю ветку на http://entlib.codeplex.com/discussions/281833):

randylevy Mon в 23:39 Нет, кеширование 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);

ОБНОВЛЕНИЕ Снова из EntLib (еще лучшее решение):

Спасибо. Может быть, это можно положить на стол для Enterprise Library 6 так как это кажется хорошей идеей?

Ради интереса, я немного усовершенствовал пример для хранения RowMapperCache как синглтон внутри EnterpriseLibraryContainer, чтобы он мог извлекаться аналогично другим объектам библиотеки предприятия. Хотя не «родной» класс Enterprise Library, используется RowMapperCache только с Enterprise Library, так что это не огромный скачок, чтобы сохранить его в контейнер (особенно если вы не используете полный 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();
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...