簡體   English   中英

屬性數量可變的實體的正確設計

[英]Proper Design for an Entity with a Variable Number of Properties

我正在實現自定義表單設計器。 現在到了我想要將布局持久保存到數據庫的地步。

技術局限性

  • NET 4.0
  • NHibernate
  • 流利的NHibernate
  • MSSQL 2008 R2

這是我提出的設計:

控制表

  • id int身份
  • 類型varchar(300)

ControlProperties表

  • id int身份
  • ControlId從FK到Controls.ID
  • 名稱varchar(300)
  • 值varchar(max)

控制等級

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並將所有值存儲為字符串的更好方法?

一些替代方法可以做到這一點。

一種解決方案是使用繼承

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);
    }
  }
}

Twitter上的芽向我指示了使用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映射圖

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM