C# 使用实体框架从不同的表创建具有列表的业务对象
我已经实现了以下数据模式:C# 使用实体框架从不同的表创建具有列表的业务对象,c#,sql-server,entity-framework,C#,Sql Server,Entity Framework,我已经实现了以下数据模式: CREATE TABLE [dbo].[Characters] ( [Id] INT NOT NULL PRIMARY KEY, [Name] NVARCHAR(50) NOT NULL ) CREATE TABLE [dbo].[Attributes] ( [Id] INT NOT NULL PRIMARY KEY, [Name] NVARCHAR(50) NULL, [DataType] NVARCHAR(50) N
CREATE TABLE [dbo].[Characters]
(
[Id] INT NOT NULL PRIMARY KEY,
[Name] NVARCHAR(50) NOT NULL
)
CREATE TABLE [dbo].[Attributes]
(
[Id] INT NOT NULL PRIMARY KEY,
[Name] NVARCHAR(50) NULL,
[DataType] NVARCHAR(50) NULL,
)
CREATE TABLE [dbo].[AttributeValues]
(
[Id] INT NOT NULL PRIMARY KEY,
[CharacterId] INT NOT NULL,
[AttributeId] INT NOT NULL,
[Text] NVARCHAR(MAX) NULL,
[Number] DECIMAL NULL,
[Flag] BIT NULL,
[Date] DATETIME NULL,
CONSTRAINT [FK_AttributeValuesCharacter] FOREIGN KEY (ChracterId) REFERENCES Characters(Id),
CONSTRAINT [FK_AttributeValuesAttribute] FOREIGN KEY (AttributeId) REFERENCES Attributes(Id)
)
表字符
保存字符,表属性
保存这些字符的属性。使用表attributeValue
,可以将属性指定给具有任何类型值的字符。就我目前的情况而言,每个字符都有一个条目以及表“Attributes”中的每个属性,当然还有一个特定的值。该值位于其类型的列中。
我选择这种设计是因为我需要一个非常灵活的数据模式,它使我能够为字符
添加任何类型的新属性
我不熟悉实体框架和C#,我需要构建类似以下业务对象的东西:
public class CharacterExtended
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public Dictionary<string, DynamicValue<T> attributes {get; set; }
}
公共类字符扩展
{
[关键]
公共int Id{get;set;}
公共字符串名称{get;set;}
公共字典实体框架无法将表映射到字典,在我看来这不是最好的方法
用这样的方法:
public class AttributeValue
{
public virtual int Id { get; set; }
public virtual int CharacterId { get; set; }
public virtual int AttributeId { get; set; }
public virtual string Text { get; set; }
public virtual decimal? Number { get; set; }
public virtual bool? Flag { get; set; }
public virtual DateTime? Date { get; set; }
public virtual Attribute Attribute { get; set; }
public virtual Character Character { get; set; }
public dynamic GetValue()
{
switch (Attribute.DataType)
{
case Attribute.ValueTypes.Text:
return Text;
case Attribute.ValueTypes.DateTime:
return Date ?? DateTime.MinValue;
case Attribute.ValueTypes.Decimal:
return Number ?? 0M;
case Attribute.ValueTypes.Boolean:
return Flag ?? false;
default:
return null;
}
}
public T? GetValue<T>() where T : struct
{
switch (typeof(T).Name)
{
case "String":
return (T)Convert.ChangeType(Text, typeof(T));
case "Decimal":
return (T)Convert.ChangeType(Number ?? 0M, typeof(T));
case "Boolean":
return (T)Convert.ChangeType(Flag ?? false, typeof(T));
case "DateTime":
return (T)Convert.ChangeType(Date ?? DateTime.MinValue, typeof(T));
}
throw new InvalidOperationException();
}
}
var dob = attributes.FirstOrDefault(x => x.Attribute.Name == "date_of_birth");
if (dob == null)
{
dob.GetValue(); // dynamic
dob.GetValue<DateTime>(); // type variable
}
公共类属性值
{
公共虚拟整数Id{get;set;}
公共虚拟int字符{get;set;}
公共虚拟int AttributeId{get;set;}
公共虚拟字符串文本{get;set;}
公共虚拟十进制数{get;set;}
公共虚拟布尔?标志{get;set;}
公共虚拟日期时间?日期{get;set;}
公共虚拟属性{get;set;}
公共虚拟字符{get;set;}
公共动态GetValue()
{
开关(属性.数据类型)
{
case Attribute.ValueTypes.Text:
返回文本;
案例属性.ValueTypes.DateTime:
返回日期??DateTime.MinValue;
case Attribute.ValueTypes.Decimal:
返回编号??0米;
case Attribute.ValueTypes.Boolean:
返回标志??假;
违约:
返回null;
}
}
公共T?GetValue()其中T:struct
{
开关(类型(T).名称)
{
大小写“字符串”:
return(T)Convert.ChangeType(Text,typeof(T));
“十进制”一词:
返回(T)转换转换类型(编号为0米,类型为(T));
案例“布尔”:
返回(T)Convert.ChangeType(标志??false,类型为(T));
案例“日期时间”:
return(T)Convert.ChangeType(日期??DateTime.MinValue,typeof(T));
}
抛出新的InvalidOperationException();
}
}
您可以这样使用它:
public class AttributeValue
{
public virtual int Id { get; set; }
public virtual int CharacterId { get; set; }
public virtual int AttributeId { get; set; }
public virtual string Text { get; set; }
public virtual decimal? Number { get; set; }
public virtual bool? Flag { get; set; }
public virtual DateTime? Date { get; set; }
public virtual Attribute Attribute { get; set; }
public virtual Character Character { get; set; }
public dynamic GetValue()
{
switch (Attribute.DataType)
{
case Attribute.ValueTypes.Text:
return Text;
case Attribute.ValueTypes.DateTime:
return Date ?? DateTime.MinValue;
case Attribute.ValueTypes.Decimal:
return Number ?? 0M;
case Attribute.ValueTypes.Boolean:
return Flag ?? false;
default:
return null;
}
}
public T? GetValue<T>() where T : struct
{
switch (typeof(T).Name)
{
case "String":
return (T)Convert.ChangeType(Text, typeof(T));
case "Decimal":
return (T)Convert.ChangeType(Number ?? 0M, typeof(T));
case "Boolean":
return (T)Convert.ChangeType(Flag ?? false, typeof(T));
case "DateTime":
return (T)Convert.ChangeType(Date ?? DateTime.MinValue, typeof(T));
}
throw new InvalidOperationException();
}
}
var dob = attributes.FirstOrDefault(x => x.Attribute.Name == "date_of_birth");
if (dob == null)
{
dob.GetValue(); // dynamic
dob.GetValue<DateTime>(); // type variable
}
var-dob=attributes.FirstOrDefault(x=>x.Attribute.Name==“出生日期”);
如果(dob==null)
{
dob.GetValue();//动态
dob.GetValue();//类型变量
}