4

想知道Enterprise Library 5.0的訪問器方法是否緩存數據讀取器的字段以及自定義類的性能,以便它不查找字段名稱使用反射的自定義類,並且在將datareader映射到對象時,不會在datareader上查找字段名稱?因爲它是一種相當昂貴的操作,以映射自定義類字段的DataReader字段每次訪問/碼塊在數據讀取器和用於訪問器方法的自定義類之間執行企業庫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; } 
} 
+1

不entlib提供了源?你不能只檢查一下嗎?另外:我知道**肯定**,「dapper-dot-net」緩存這個,所以它*可能*是一個選項來使用它,和'var r = connection.Query (「SELECT * FROM Region」) .ToList();' –

回答

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

所以沒有;我看不到有任何緩存的證據。你可以添加一些,或者你可以使用domething已經做materializer和參數緩存(*咳嗽* 短小精悍點網 *咳嗽*)

+1

感謝馬克 - 我在entlib支持論壇上發佈了相同的內容,並得到了一個很好的簡單解決方法。檢查這個線程 - http://entlib.codeplex.com/discussions/281833 – Raj

2

這裏是一個簡單而漂亮的黑客通過entlib支持團隊建議(你可以在http://entlib.codeplex.com/discussions/281833檢查全螺紋):在下午11時39分沒有

randylevy週一,有不 的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從EntLib再次(甚至更好的解決方案):

感謝。也許,它可以放在企業圖書館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(); 
     } 
    } 
}