使用 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
        }
    }
}