我的所有实体(映射到数据库表)都从一个实体类继承,其上有一个名为Attributes的动态组件,例如:
public abstract class Entity<T> {
public virtual T Id { get; set; }
private IDictionary _attributes;
public virtual IDictionary Attributes {
get { return _attributes ?? (_attributes = new Hashtable()); }
set { _attributes = value; }
}
}
Attributes集合允许我为每个实体添加额外的字段,而无需直接更改实体本身。这使我可以使我的应用程序更加模块化。
例如说我有以下实体:
public class User : Entity<int> {
public virtual string Name { get; set; }
}
现在说我有一个论坛模块,需要针对用户的NumPosts属性。我会在数据库中的Users表中添加该字段。此字段不可为空,默认值为0.然后,使用动态组件对用户实体映射字段。
但是当我尝试插入用户时说:
session.Save(new User() { Name = "Test" });
它抛出一个错误,因为它期望我为NumPosts设置一个值,生成的SQL将是这样的:
INSERT INTO Users(Name,NumPosts)VALUES('Test',NULL)
然而,NumPosts不允许空值,因此也不允许出错。理想情况下,如果Attributes集合不包含NumPosts的条目,我想要说下面的内容:
插入用户(名称)VALUES('测试')
另一种方法是说以下哪种方法可以正常工作:
session.Save(new User() { Name = "Test", Attributes = new Hashtable() { { "NumPosts", 0 } } });
我遇到的问题是我不希望模块彼此依赖,我不能说这个。
供参考,这是一个简单的会话工厂方法版本,它映射NumPosts字段:
return Fluently.Configure()
...
.ExposeConfiguration(c => {
// Get the persistent class
var persistentClass = c.GetClassMapping("User");
// Create the attributes component
var component = new Component(persistentClass);
// Create a simple value
var simpleValue = new SimpleValue(persistentClass.Table);
// Set the type name
simpleValue.TypeName = "Int32";
// Create a new db column specification
var column = new Column("NumPosts");
column.Value = simpleValue;
column.Length = 10;
column.IsNullable = false;
column.DefaultValue = "0";
// Add the column to the value
simpleValue.AddColumn(column);
// Ad the value to the component
component.AddProperty(new Property() { Name = column.Name, Value = simpleValue });
// Add the component property
persistentClass.AddProperty(new Property() { Name = "Attributes", Value = component });
})
.BuildConfiguration();
如果有可能,有人可以告诉我,我很感激。感谢
答案 0 :(得分:1)
您知道如何使其按上述方式工作:
......另一种方法是说以下哪种方法可以正常工作:
session.Save(new User()
{
Name = "Test", Attributes = new Hashtable() { { "NumPosts", 0 } }
});
...我遇到的问题是我不希望模块彼此依赖,我真的不能这样说......
如果最大的问题是明确的Attributes
初始化(“... 我不希望模块具有依赖性 ...”) 我们可以使用:
所以,使用像这样的Listener:
[Serializable]
public class MyPersistListener : NHibernate.Event.ISaveOrUpdateEventListener
{
public void OnSaveOrUpdate(SaveOrUpdateEvent @event)
{
var entity = @event.Entity as Entity<int>; // some interface IHaveAttributes
if (entity == null) // would be more appropriate
{
return;
}
var numPosts = entity.Attributes["NumPosts"] as int?;
if (numPosts.HasValue)
{
return;
}
entity.Attributes["NumPosts"] = 0;
}
}
基于此文档摘要:
Configuration cfg = new Configuration();
ILoadEventListener[] stack = new ILoadEventListener[] { new MyLoadListener(), new DefaultLoadEventListener() };
cfg.EventListeners.LoadEventListeners = stack;
在我们的案例中,这应该是init:
.ExposeConfiguration(c => {
var stack = new ISaveOrUpdateEventListener [] { new MyPersistListener() };
c.EventListeners.SaveEventListeners= stack;