1

我正在实现一个自定义表单设计器。我现在到了我想将布局保存到数据库的地步。

技术限制

  • .NET 4.0
  • 休眠
  • 流畅的 NHibernate
  • MSSQL 2008 R2

这是我想出的一个设计:

控制表

  • Id int 身份
  • 输入 varchar(300)

控制属性表

  • Id int 身份
  • ControlId int FK 到 Controls.ID
  • 名称 varchar(300)
  • 值 varchar(最大值)

控制类

public class Control
{
  public virtual int Id { get; set; }
  public virtual string Type { get; set; }
  public virtual Dictionary<string, string> Properties { get; set; }
}

然后我会映射它,这样我就可以做这样的事情来重新加载布局:

var controls = GetListOfControlsUsingNHibernate();
foreach (var control in controls){
  var newControl = CreateControlFromType(control.Type);
  SetPropertiesViaTypeDescriptor(newControl, control.Properties);
  this.Controls.Add(newControl);
}

我有两个问题。

  1. 如何使用 Fluent NHibernate 映射这个?
  2. 有没有更好的方法不涉及 EAV 并将所有值存储为字符串?
4

2 回答 2

1

一些替代方法可以做到这一点。

一种解决方案是使用继承

public abstract class Control
{
    // ...
}
public class TextBox : Control
{
    public virtual string Text { get; set; }
}
public class MaskedTextBox : TextBox
{
    public virtual string Mask { get; set; }
}

另一种是使用不同种类的属性

public class Control
{
  public virtual ISet<Property> Properties { get; set; }
} 
public abstract class Property
{
  public virtual string Name { get; set; }
}
public class IntProperty : Property
{
  public virtual int Value { get; set; }
}
public class DecimalProperty : Property
{
  public virtual decimal Value { get; set; }
}
// ...

还有一个是使用接口

public abstract class Control
{
}
public class TextBox : Control, ITextControl
{
  public virtual string Text { get; set; }
}


public class ConcreteControlMap<T> : SubclassMap<T> where T : Control
{
  public ConcreteControlMap()
  {
    if(typeof(ITextControl).IsAssignableFrom(typeof(T)))
    {
      Map(c => ((ITextControl)c).Text);
    }
  }
}
于 2013-02-20T06:46:59.970 回答
0

twitter 上的一个 bud 为我指出了使用 Fluent NHibernate 进行映射的正确方向:

首先创建一个表Properties来保存我们的属性:

╔═══════════╦══════════════╦═══════════════╗
║ ControlId ║ PropertyName ║ PropertyValue ║
╚═══════════╩══════════════╩═══════════════╝

现在像这样改变我们的映射:

public class ControlMap : ClassMap<Control>
{
    public ControlMap()
    {
        Table("Controls");
        Id(x => x.Id);
        Map(x => x.Type);
        HasMany(x => x.Properties).Table("ControlProperties")
            .AsMap<string>(index => index.Column("PropertyName").Type<string>(),
                           element => element.Column("PropertyValue").Type<string>())
            .Cascade.All(); 
    }
}

有关这背后的 hbm xml 的一些背景信息,请参见 Ayende 的NHibernate Mapping Map

于 2013-02-21T20:03:26.290 回答