Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Model First: how to add property of type Color?

I'm creating a new database with the model-first approach and I want to add a column to a table of the type System.Drawing.Color but I don't have this option in the properties list.

Is there a way to use more data types than the ones available?

like image 820
Mihai Bratulescu Avatar asked Jul 15 '14 10:07

Mihai Bratulescu


2 Answers

Another option here, is to use adapt the answer from Entity Framework 6 Code First - Custom Type Mapping

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

The NotMapped attribute makes the entity framework not try to map the Color property to a column in the database.

like image 75
bobbaluba Avatar answered Oct 17 '22 07:10

bobbaluba


One option here is to have an int version of the ARGB colours:

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

In your mapping, ignore the Color property specifically by using the fluent bindings:

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

From here you now can store the data from any Color's static methods:

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

One alternative chosen in the comments is to serialize as XML.

The code above uses an integer, as this uses native, efficient data types to SQL Server and is easily maintainable.

The XML version would take up much more space, is less maintainable and will now add complexity to searching for a specific colour. An expanded System.Drawing.Color type would look like this:

<Color>
    <A>123</A>
    <R>45</R>
    <G>67</G>
    <B>89</B>
    <ScA>0.482352942</ScA>
    <ScR>0.026241‌​2224</ScR>
    <ScG>0.0561284944</ScG>
    <ScB>0.09989873</ScB>
</Color>

Which is easier to search for the color blue?

For the int type, this would be:

SELECT COUNT(1) FROM Customer cust
INNER JOIN Color col
ON cust.FavouriteColorId = color.Id
WHERE col.Argb = 0xFF0000FF

For the XML type:

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'
like image 2
Dominic Zukiewicz Avatar answered Oct 17 '22 08:10

Dominic Zukiewicz