我覺得你可以去一個適合雙方的關係方和麪向對象方面是映射和對象模型到數據庫中的TPC抽象,它最接近已經非常接近你的桌子結構。爲了簡單起見,我將在EF 4.3.1中使用Code First進行展示。
讓我們定義一個簡單的對象模型,像這樣:
public class Property
{
public int Id { get; set; }
public string Name { get; set; }
public int ValueId { get; set; }
public virtual Value Value { get; set; }
}
public abstract class Value
{
public int Id { get; set; }
}
public class ValueString : Value
{
public string Value { get; set; }
public override string ToString()
{
return "String value of " + Value;
}
}
public class ValueInteger : Value
{
public int Value { get; set; }
public override string ToString()
{
return "Integer value of " + Value;
}
}
public class ValueBoolean : Value
{
public bool Value { get; set; }
public override string ToString()
{
return "Boolean value of " + Value;
}
}
(我把一些的ToString方法只是爲了很容易地看到發生了什麼事情,當我們使用這些類。)
這可以使用TPC映射,使得每種類型都有自己的表:
public class PropertyAndValuesContext : DbContext
{
public DbSet<Property> Properties { get; set; }
public DbSet<Value> Values { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<ValueString>().Map(
m =>
{
m.MapInheritedProperties();
m.ToTable("ValueString");
});
modelBuilder.Entity<ValueInteger>().Map(
m =>
{
m.MapInheritedProperties();
m.ToTable("ValueInteger");
});
modelBuilder.Entity<ValueBoolean>().Map(
m =>
{
m.MapInheritedProperties();
m.ToTable("ValueBoolean");
});
}
}
所以,現在的表,我們有符合您在您的問題開始提供的佈局,除了TYPEID合作由於在此不需要,因此缺少列。
讓我們寫一個初始化函數和一個控制檯應用程序添加一些測試數據並顯示它:
public class TestInitializer : DropCreateDatabaseAlways<PropertyAndValuesContext>
{
protected override void Seed(PropertyAndValuesContext context)
{
new List<Property>
{
new Property { Name = "PropWithBool", Value = new ValueBoolean { Id = 1, Value = true } },
new Property { Name = "PropWithString1", Value = new ValueString { Id = 2, Value = "Magic" } },
new Property { Name = "PropWithString2", Value = new ValueString { Id = 3, Value = "Unicorn" } },
new Property { Name = "PropWithInt1", Value = new ValueInteger { Id = 4, Value = 6 } },
new Property { Name = "PropWithInt2", Value = new ValueInteger { Id = 5, Value = 7 } },
}.ForEach(p => context.Properties.Add(p));
}
}
public class Program
{
public static void Main(string[] args)
{
Database.SetInitializer(new TestInitializer());
using (var context = new PropertyAndValuesContext())
{
foreach (var property in context.Properties)
{
Console.WriteLine("{0} with {1}", property.Name, property.Value);
}
}
}
}
運行此打印出:
PropWithBool with Boolean value of True
PropWithString1 with String value of Magic
PropWithString2 with String value of Unicorn
PropWithInt1 with Integer value of 6
PropWithInt2 with Integer value of 7
你可以看到,我們能夠輕鬆地添加不同類型的值,將它們存儲在適當的表中,然後再查詢這些值。
現在,也許你真的想要一個屬性的返回值作爲「對象」類型在你的例子中。好了,現在我們可以用一個簡單的抽象屬性做到這一點:
public abstract class Value
{
public int Id { get; set; }
public abstract object TheValue { get; set; }
}
public class ValueString : Value
{
public string Value { get; set; }
public override object TheValue
{
get { return Value; }
set { Value = (string)value; }
}
public override string ToString()
{
return "String value of " + Value;
}
}
public class ValueInteger : Value
{
public int Value { get; set; }
public override object TheValue
{
get { return Value; }
set { Value = (int)value; }
}
public override string ToString()
{
return "Integer value of " + Value;
}
}
public class ValueBoolean : Value
{
public bool Value { get; set; }
public override object TheValue
{
get { return Value; }
set { Value = (bool)value; }
}
public override string ToString()
{
return "Boolean value of " + Value;
}
}
你也可以想像這樣做,如果你想:
public class Property
{
public int Id { get; set; }
public string Name { get; set; }
public int ValueId { get; set; }
public virtual Value Value { get; set; }
public object TheValue
{
get { return Value.TheValue; }
set { Value.TheValue = value; }
}
}
最後,如果你真的需要typeid的屬性/列在屬性實體/表,然後你可以添加它,但你必須確保你將它設置爲適當的值,因爲它不需要映射。
一些數據庫(Oracle)允許使用這樣的密鑰。你沒有提到你正在使用哪個數據庫。話雖如此,這種設計不適合標準的SQL DB或EF。我建議你以不同的方式解決你的問題。 – 2012-03-27 16:38:29
感謝Craig,我正在使用MS SQL Server。我可以用代碼中的額外公共功能來管理這個問題。但它只會讓我的團隊成員感到困惑,而且會讓事情變得更加複雜。我需要像(字符串)SomeProperty.Value或(int)SomeProperty.Value這樣的使用方法。我不想執行額外的功能來獲得物業的價值。 – oruchreis 2012-03-27 17:23:26