我正在使用模型优先方法创建一个新数据库,我想向
System.Drawing.Color
类型的表添加一列,但属性列表中没有此选项。
有没有办法使用比可用数据类型更多的数据类型?
此处的另一个选项是使用 Entity Framework 6 Code First - 自定义类型映射
中的答案public class MyLittlePony {
public string Name { get; set; }
public Int32 Argb {
get {
return Color.ToArgb();
}
set {
Color = Color.FromArgb(value);
}
}
[NotMapped]
public Color Color { get; set; }
}
NotMapped
属性使实体框架不会尝试将 Color 属性映射到数据库中的列。
这里的一个选择是拥有 ARGB 颜色的
int
版本:
public class ColorData
{
public int Id { get; set; }
public int Argb { get; set; }
public System.Drawing.Color Color
{
get { return new System.Drawing.Color.FromArgb(this.Argb); }
set
{
if(value!=null)
this.Argb = value.ToArgb();
else
this.Argb = 0;
}
}
}
在映射中,通过使用连贯绑定专门忽略
Color
属性:
protected void override OnModelCreating(ModelBuilder builder)
{
var colorTable = builder.Entity<ColorData>();
colorTable.HasKey(x => x.Id).HasColumnName("COLOR_ID");
colorTable.Property(x => x.Argb).HasColumnName("COLOR_ARGB");
colorTable.Ignore(x=>x.Color);
colorTable.ToTable("COLOR_DATA");
}
从这里您现在可以存储来自任何 Color 静态方法的数据:
ColorData data = new ColorData();
data.Color = Color.Black;
data.Color = Color.FromName("Black");
data.Color = Color.FromArgb( 0xFF000000 );
data.Color = Color.FromArgb( 255, 0, 0, 0 );
注释中选择的一种替代方法是序列化为 XML。
上面的代码使用整数,因为它使用 SQL Server 原生、高效的数据类型,并且易于维护。
XML 版本会占用更多空间,不易维护,并且现在会增加搜索特定颜色的复杂性。扩展的
System.Drawing.Color
类型如下所示:
<Color>
<A>123</A>
<R>45</R>
<G>67</G>
<B>89</B>
<ScA>0.482352942</ScA>
<ScR>0.0262412224</ScR>
<ScG>0.0561284944</ScG>
<ScB>0.09989873</ScB>
</Color>
蓝色哪个更容易搜索?
对于
int
类型,这将是:
SELECT COUNT(1) FROM Customer cust
INNER JOIN Color col
ON cust.FavouriteColorId = color.Id
WHERE col.Argb = 0xFF0000FF
对于 XML 类型:
SELECT COUNT(1) FROM Customer cust
INNER JOIN Color col
ON cust.FavouriteColorId = color.Id
WHERE col.ArgbXml.value('/Color/A') = N'255'
AND col.ArgbXml.value('/Color/R') = N'0'
AND col.ArgbXml.value('/Color/G') = N'0'
AND col.ArgbXml.value('/Color/B') = N'255'
现在是ef core 8, 我只是在寻找将颜色转换为可存储内容的方法。 所以如果其他人也会寻找它:
到位:
builder.Property(x => x.Color)
.HasConversion(c => c.ToArgb(), i => Color.FromArgb(i))
.IsRequired();
全球:
public class ColorToIntConverter : ValueConverter<Color, int>
{
public ColorToIntConverter() : base(v => v.ToArgb(), v => Color.FromArgb(v))
{
}
}
然后在上下文中:
protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
{
configurationBuilder.Properties<Color>().HaveConversion<ColorToIntConverter>();
}