使用 NHibernate 和 DevExpress GridView 的 Automapper - 缓存
Automapper With NHibernate and DevExpress GridView - Caching
我的 WebForms 项目使用 NHibernate class 库作为我们 Oracle 数据库的 OR 映射器。 NHibernate 库已经过全面测试,可以正常工作。
Global.asax.cs:
void Application_Start(object sender, EventArgs e)
{
RouteConfig.RegisterRoutes(RouteTable.Routes);
var cnnConfig = ""; //contains connection string information for NH
NHibernateClassLibrary.init(cnnConfig); //initializes NHibernate
var profileType = typeof(AutoMapper.Profile);
// Get an instance of each Profile in the executing assembly.
var profiles = Assembly.GetExecutingAssembly().GetTypes()
.Where(t => profileType.IsAssignableFrom(t)
&& t.GetConstructor(Type.EmptyTypes) != null)
.Select(Activator.CreateInstance)
.Cast<Profile>();
// Initialize AutoMapper with each instance of the profiles found.
Mapper.Initialize(a => profiles.ForEach(a.AddProfile)); //ForEach is an extension method
}
ExtensionMethods.cs:
public static class ExtensionMethods
{
public static void ForEach<T>(this IEnumerable<T> enumerable,
Action<T> action)
{
foreach (T item in enumerable) { action(item); }
}
}
SampleProfile.cs:
namespace MyProjectName.AutomapperProfiles
{
public class EntityOneProfile : Profile
{
protected override void Configure()
{
base.Configure();
Mapper.CreateMap<NHibernateClassLibrary.Entities.EntityOne, EntityOnePoco>();
}
}
}
EntityOne.cs:
namespace NHibernateClassLibrary.Entities
{
public class EntityOne
{
public virtual string PropertyOne { get; set; }
public virtual string PropertyTwo { get; set; }
public virtual string PropertyThree { get; set; }
}
}
EntityOnePoco.cs:
namespace MyProjectName.GridEntities
{
public class EntityOnePoco
{
public string PropertyOne { get; set; }
public string PropertyTwo { get; set; }
public string PropertyThree { get; set; }
}
}
MyPage.aspx.cs:
namespace MyProjectName
{
public partial class MyPage : System.Web.UI.Page
{
//This gets us access to the NHibernate Class Library
IDATABASE DataBase = Microsoft.Practices.ServiceLocation.ServiceLocator.Current.GetInstance<IDATABASE>();
protected void Page_Load(object sender, EventArgs e)
{
var EntityOneRaw = DataBase.EntityOne.ToList();
var EntityOneObjects = EntityOneRaw.Select(q => AutoMapper.Mapper.Map<NHibernateClassLibrary.Entities.EntityOne, EntityOnePoco>(q)).ToList();
GridViewObject.DataSource = new BindingList<EntityOnePoco>(EntityOneObjects);
GridViewObject.DataBind();
}
protected void ButtonOne_Click(object sender, EventArgs e)
{
var Item = DataBase.EntityOne.First();
Item.PropertyTwo = "New Value";
DataBase.SaveChanges(); //NHibernate call to commit
}
}
}
MyPage.aspx:
<!--Other lines truncated-->
<dx:ASPxGridView ID="GridViewObject" runat="server" KeyFieldName="PropertyOne">
</dx:ASPxGridView>
<asp:Button ID="ButtonOne" runat="server" Text="Take Action" OnClick="ButtonOne_Click" />
page_load 方法工作正常。网格将加载数据库的当前值,例如第一个条目的 "PropertyTwo" 等于 "Old Value"。如果我按下 ButtonOne,ButtonOne_Click 方法将触发并适当地更新 EntityOne table 中的第一个条目。我已经在 Oracle 中直接确认了这一点。此外,在此操作完成后立即设置的断点表明 NHibernateClassLibrary 正在适当地获取新的 属性。但是,GridView 仍然显示 "Old Value",直到我停止 IIS/Debugging 并重新启动。
我的第一直觉是在某处启用了缓存,但我已经确认 NHibernate 没有缓存旧值。如果数据库中的 EntityOne 是最新的,我如何强制 AutoMapped EntityOnePoco 同时更新?我是不是漏掉了什么简单的东西?
我找到的解决方案是调用 DataBase.Clear(),本质上是在填充 EntityOneRaw 对象之前清除一级 NHibernate 缓存,如下例所示。我的用例受益于一级缓存,因此在我的实际代码中,我只在必要时调用 Clear() 方法。
namespace MyProjectName
{
public partial class MyPage : System.Web.UI.Page
{
//This gets us access to the NHibernate Class Library
IDATABASE DataBase = Microsoft.Practices.ServiceLocation.ServiceLocator.Current.GetInstance<IDATABASE>();
protected void Page_Load(object sender, EventArgs e)
{
DataBase.Clear(); //clear the first-level cache in NHibernaet
var EntityOneRaw = DataBase.EntityOne.ToList();
var EntityOneObjects = EntityOneRaw.Select(q => AutoMapper.Mapper.Map<NHibernateClassLibrary.Entities.EntityOne, EntityOnePoco>(q)).ToList();
GridViewObject.DataSource = new BindingList<EntityOnePoco>(EntityOneObjects);
GridViewObject.DataBind();
}
protected void ButtonOne_Click(object sender, EventArgs e)
{
var Item = DataBase.EntityOne.First();
Item.PropertyTwo = "New Value";
DataBase.SaveChanges(); //NHibernate call to commit
}
}
}
我的 WebForms 项目使用 NHibernate class 库作为我们 Oracle 数据库的 OR 映射器。 NHibernate 库已经过全面测试,可以正常工作。
Global.asax.cs:
void Application_Start(object sender, EventArgs e)
{
RouteConfig.RegisterRoutes(RouteTable.Routes);
var cnnConfig = ""; //contains connection string information for NH
NHibernateClassLibrary.init(cnnConfig); //initializes NHibernate
var profileType = typeof(AutoMapper.Profile);
// Get an instance of each Profile in the executing assembly.
var profiles = Assembly.GetExecutingAssembly().GetTypes()
.Where(t => profileType.IsAssignableFrom(t)
&& t.GetConstructor(Type.EmptyTypes) != null)
.Select(Activator.CreateInstance)
.Cast<Profile>();
// Initialize AutoMapper with each instance of the profiles found.
Mapper.Initialize(a => profiles.ForEach(a.AddProfile)); //ForEach is an extension method
}
ExtensionMethods.cs:
public static class ExtensionMethods
{
public static void ForEach<T>(this IEnumerable<T> enumerable,
Action<T> action)
{
foreach (T item in enumerable) { action(item); }
}
}
SampleProfile.cs:
namespace MyProjectName.AutomapperProfiles
{
public class EntityOneProfile : Profile
{
protected override void Configure()
{
base.Configure();
Mapper.CreateMap<NHibernateClassLibrary.Entities.EntityOne, EntityOnePoco>();
}
}
}
EntityOne.cs:
namespace NHibernateClassLibrary.Entities
{
public class EntityOne
{
public virtual string PropertyOne { get; set; }
public virtual string PropertyTwo { get; set; }
public virtual string PropertyThree { get; set; }
}
}
EntityOnePoco.cs:
namespace MyProjectName.GridEntities
{
public class EntityOnePoco
{
public string PropertyOne { get; set; }
public string PropertyTwo { get; set; }
public string PropertyThree { get; set; }
}
}
MyPage.aspx.cs:
namespace MyProjectName
{
public partial class MyPage : System.Web.UI.Page
{
//This gets us access to the NHibernate Class Library
IDATABASE DataBase = Microsoft.Practices.ServiceLocation.ServiceLocator.Current.GetInstance<IDATABASE>();
protected void Page_Load(object sender, EventArgs e)
{
var EntityOneRaw = DataBase.EntityOne.ToList();
var EntityOneObjects = EntityOneRaw.Select(q => AutoMapper.Mapper.Map<NHibernateClassLibrary.Entities.EntityOne, EntityOnePoco>(q)).ToList();
GridViewObject.DataSource = new BindingList<EntityOnePoco>(EntityOneObjects);
GridViewObject.DataBind();
}
protected void ButtonOne_Click(object sender, EventArgs e)
{
var Item = DataBase.EntityOne.First();
Item.PropertyTwo = "New Value";
DataBase.SaveChanges(); //NHibernate call to commit
}
}
}
MyPage.aspx:
<!--Other lines truncated-->
<dx:ASPxGridView ID="GridViewObject" runat="server" KeyFieldName="PropertyOne">
</dx:ASPxGridView>
<asp:Button ID="ButtonOne" runat="server" Text="Take Action" OnClick="ButtonOne_Click" />
page_load 方法工作正常。网格将加载数据库的当前值,例如第一个条目的 "PropertyTwo" 等于 "Old Value"。如果我按下 ButtonOne,ButtonOne_Click 方法将触发并适当地更新 EntityOne table 中的第一个条目。我已经在 Oracle 中直接确认了这一点。此外,在此操作完成后立即设置的断点表明 NHibernateClassLibrary 正在适当地获取新的 属性。但是,GridView 仍然显示 "Old Value",直到我停止 IIS/Debugging 并重新启动。
我的第一直觉是在某处启用了缓存,但我已经确认 NHibernate 没有缓存旧值。如果数据库中的 EntityOne 是最新的,我如何强制 AutoMapped EntityOnePoco 同时更新?我是不是漏掉了什么简单的东西?
我找到的解决方案是调用 DataBase.Clear(),本质上是在填充 EntityOneRaw 对象之前清除一级 NHibernate 缓存,如下例所示。我的用例受益于一级缓存,因此在我的实际代码中,我只在必要时调用 Clear() 方法。
namespace MyProjectName
{
public partial class MyPage : System.Web.UI.Page
{
//This gets us access to the NHibernate Class Library
IDATABASE DataBase = Microsoft.Practices.ServiceLocation.ServiceLocator.Current.GetInstance<IDATABASE>();
protected void Page_Load(object sender, EventArgs e)
{
DataBase.Clear(); //clear the first-level cache in NHibernaet
var EntityOneRaw = DataBase.EntityOne.ToList();
var EntityOneObjects = EntityOneRaw.Select(q => AutoMapper.Mapper.Map<NHibernateClassLibrary.Entities.EntityOne, EntityOnePoco>(q)).ToList();
GridViewObject.DataSource = new BindingList<EntityOnePoco>(EntityOneObjects);
GridViewObject.DataBind();
}
protected void ButtonOne_Click(object sender, EventArgs e)
{
var Item = DataBase.EntityOne.First();
Item.PropertyTwo = "New Value";
DataBase.SaveChanges(); //NHibernate call to commit
}
}
}