在问题Mapping to an Enum bit flag in Nhibernate中,接受的答案建议只使用整数字段来存储枚举类型的位掩码。虽然这确实有效,但我不想使用这种方法,因为它会混淆数据库中的信息。
假设我有这个列举:
[Flags]
public enum Status
{
None = 0,
Foo = 1,
Bar = 2,
Baz = 4
}
我想使用以下架构来表示它:
CREATE TABLE Widgets
(
Id int NOT NULL IDENTITY(1, 1) PRIMARY KEY,
Description nvarchar(100) NOT NULL,
-- Status fields start here
IsFoo bit NOT NULL,
IsBar bit NOT NULL,
IsBaz bit NOT NULL
)
我可以使用NHibernate做到这一点 - 最好没有很多丑陋的黑客攻击吗?如果是这样,怎么样?
如果没有,除了在配置表中定义每个可能的标志组合之外,还有其它方法可以保持数据的可发现性吗?
(注意:我更喜欢Fluent NHibernate解决方案,但我可能会混淆XML映射。)
答案 0 :(得分:2)
抱歉这里没有完整答案我一直在努力在这台机器上设置NHib /流利。我采用了一种旧的自定义类型,并将其更改为符合您的状态枚举。我认为在nHibernate的更高版本中,一些方法接口可能已经改变,但我认为它提供了一个很好的起点。
class StatusUserType : ICompositeUserType
{
public object GetPropertyValue(object component, int property)
{
// 0 = foo
// 1 = bar
// 2 = baz
Status status = (Status)component;
if (property == 0)
{
return status |= Status.Foo;
}
else if (property == 1)
{
return status |= Status.Bar;
}
else
{
return status |= Status.Baz;
}
}
public void SetPropertyValue(object component, int property, object value)
{
throw new NotImplementedException();
}
public new bool Equals(object x, object y)
{
if (x == y) return true;
if (x == null || y == null) return false;
return x.Equals(y);
}
public object NullSafeGet(System.Data.IDataReader dr, string[] names, ISessionImplementor session, object owner)
{
if (dr == null)
{
return null;
}
string fooColumn = names[0];
string barColumn = names[1];
string bazColumn = names[2];
bool isFoo = NHibernateUtil.Boolean.NullSafeGet(dr, fooColumn, session, owner);
bool isBar = NHibernateUtil.Boolean.NullSafeGet(dr, barColumn, session, owner);
bool isBaz = NHibernateUtil.Boolean.NullSafeGet(dr, bazColumn, session, owner);
Status status = (isFoo ? Status.Foo : Status.None) | (isBar ? Status.Bar : Status.None) | (isBaz ? Status.Baz : Status.None);
return status;
}
public void NullSafeSet(System.Data.IDbCommand cmd, object value, int index, ISessionImplementor session)
{
if (value == null)
return;
Status status = (Status)value;
bool isFoo = ((status & Status.Foo) != 0);
bool isBar = ((status & Status.Bar) != 0);
bool isBaz = ((status & Status.Baz) != 0);
NHibernateUtil.Boolean.NullSafeSet(cmd, isFoo, index, session);
NHibernateUtil.Boolean.NullSafeSet(cmd, isBar, index + 1, session);
NHibernateUtil.Boolean.NullSafeSet(cmd, isBaz, index + 2, session);
}
public object DeepCopy(object value)
{
return (Status)value;
}
public object Disassemble(object value, ISessionImplementor session)
{
return DeepCopy(value);
}
public object Assemble(object cached, ISessionImplementor session, object owner)
{
return DeepCopy(cached);
}
public string[] PropertyNames
{
get { return new string[3] { "IsFoo", "IsBar", "IsBaz" }; }
}
public IType[] PropertyTypes
{
get
{
return new IType[3] { NHibernateUtil.Boolean, NHibernateUtil.Boolean, NHibernateUtil.Boolean };
}
}
public Type ReturnedClass
{
get { return typeof(Status); }
}
public bool IsMutable
{
get { return false; }
}
答案 1 :(得分:0)
Status
属性
事情的影响:
public class Kuku
{
private virtual bool IsFoo {get; set;}
private virtual bool IsBar {get; set;}
private virtual bool IsBaz {get; set;}
public virtual Status Stat
{
get
{
Status retval = Status.None;
if (IsFoo)
{
retVal |= Status.Foo;
}
//etc...
}
set
{
IsFoo = value & Status.Foo;
//etc...
}
}
}