【问题标题】:Transforming legacy values with NHibernate使用 NHibernate 转换遗留值
【发布时间】:2011-03-09 23:52:49
【问题描述】:

我们有一些旧表,其中包含我们发现难以使用的旧架构。

是否可以使用 NHibernate 将其中一些数据转换为更好的模型?

例如,我们可能有一个整数状态列,我们希望将其分解为多个属性。

Legacy status: 0 - Active, 1 - Inactive, 2 - TemporarilyInactive, 3 - etc

我们想要这样的东西:

bool IsActive { get; set; }
Status Status { get; set; }

(其中Status 是一个枚举)

我知道我们可以使用protected 字段来获取状态,然后定义额外属性的 getter 以根据支持字段返回适当的值,但我很确定这将禁用能够根据这些属性进行查询。

但是,通过这种方式,我们将无法执行诸如 .Query(p => p.IsActive) 之类的查询并将其转换为诸如 where status = 0 之类的 SQL,对吧?

是不是只能通过自定义IUserTypes?如果是这样,是否有任何帮助框架可以更轻松地使用 IUserType 以实现此目的?

其他人如何处理这个问题?

【问题讨论】:

    标签: nhibernate legacy brownfield


    【解决方案1】:

    您可以创建自己的“枚举”类。

    public class Status
    {
        //The numeric (legacy) code
        public int Code{ get;private set; }
        //The human readable name
        public string Name{ get; private set; }
        //If this status is an active status
        public bool IsActive { get; private set; }
    
        private Status(int aCode, string aName, bool anIsActive)
        {
            Code = aCode;
            Name = aName;
            IsActive = anIsActive;
        }
    
        public static Status ACTIVE = new Status(0, "Active");
        public static Status INACTIVE = new Status(1, "Inactive");
        //Other status here...
        private static Status[] STATUSES = {Active,Inactive,...};
    
        //Returns a status based on the passed in code
        public static Status GetByCode(int aCode)
        {
            return STATUSES.FirstOrDefault(aStatus => aStatus.Code == aCode);
        }
    }
    

    然后您可以让 NHibernate 使用旧值设置一个私有变量,并拥有一个在枚举和旧值之间转换的 getter/setter。

    private int theLegacyStatus;  //This is the value that NHibernate sets
    public Status
    {
        get
        {
            return Status.GetStatusByCode(theLegacyStatus);
        }
        set
        {
            theLegacyStatus = value.Code;
        }
    }
    

    然后您可以在 NHibernate 查询中使用此枚举:.Query(p => p.Status.Code)

    【讨论】:

    • 如果 NHibernate 在映射中使用了 LegacyStatus,查询 p.Status.Code 将不起作用。它对包装状态属性一无所知,因此不能期望它知道为这样的查询生成什么 SQL。 (已经尝试过这样的事情并得到一个异常,如“无法解析属性:状态”)
    • 您是否使用标准?我使用此方法的方式是var criteria = DetachedCriteria.For<ObjectType>.Add(Restrictions.Eq("theLegacyStatus"), 0);,它将返回所有状态为活动(0)的ObjectType对象。
    • 是的,我知道标准或 HQL 会起作用,但这会破坏模型。您必须了解实体的内部结构才能执行查询,这是不好的设计。我一直在寻找更好的解决方案。不过感谢您的回答。
    猜你喜欢
    • 2011-05-22
    • 1970-01-01
    • 2012-12-18
    • 1970-01-01
    • 2010-12-25
    • 2012-09-03
    • 1970-01-01
    • 2020-01-05
    • 1970-01-01
    相关资源
    最近更新 更多