Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Entity Framework Code First - Virtual Property Column Naming

I'm using EF Code First (4.3.1) on a personal ASP.NET MVC 3 project, with a very simple domain model, and I'm almost at the point where EF will generate the DB schema the way I want it to.

The domain model has two classes: Painting and Gallery. Each Painting belongs to a single Gallery, and the Gallery has two virtual properties pointing to Painting: One to indicate which of the painting is it's cover image, and one for which of the paintings is the Slider image displayed on the home page.

The classes are as follow. I've removed some annotations and irrelevant properties to make it readable.

public class Gallery
{
    public Gallery()
    {
        Paintings = new List<Painting>();
    }

    [ScaffoldColumn(false)]
    [Key]
    public int GalleryId { get; set; }

    public string Name { get; set; }

    [ScaffoldColumn(false)]
    [Column("LaCover")]
    public Painting Cover { get; set; }

    [ScaffoldColumn(false)]
    [Column("ElSlider")]
    public Painting Slider { get; set; }

    [ScaffoldColumn(false)]
    public virtual List<Painting> Paintings { get; set; }
}

and painting:

public class Painting
{
    [ScaffoldColumn(false)]
    [Key]
    public int PaintingId { get; set; }

    public string Name { get; set; }

    public int GalleryId { get; set; }

    [Column("GalleryId")]
    [ForeignKey("GalleryId")]
    [InverseProperty("Paintings")]
    public virtual Gallery Gallery { get; set; }

    public string Filename { get; set; }
}

It generates a correct db schema for both classes and its relationships, the only small issue I have is that I haven't found a way to control the column names it gives to the virtual properties of Cover and Slider in the Gallery table.

It'll name them Cover_PaintingId and Slider_PaintingId.

I tried using the [Column("columnNameHere")] attribute, but that doesn't affect it at all. As in "I typed a certain non related word and it didnt show up in the schema".

I'd like to name it CoverPaintingId, without the underscore.

Any help is greatly appreciated. Thanks

like image 986
GR7 Avatar asked Aug 07 '12 17:08

GR7


People also ask

How do I mention primary key in Entity Framework code First?

The Code First primary key convention is: Property with name " Id " or {class name} + " Id " will act as the primary key for that entity. If you will run the application, it will create _MigrationHistory and Students tables where " StudentId " is the primary key of the Students table.

How do I code first in Entity Framework?

Step 1 − First, create the console application from File → New → Project… Step 2 − Select Windows from the left pane and Console Application from the template pane. Step 3 − Enter EFCodeFirstDemo as the name and select OK. Step 4 − Right-click on your project in the solution explorer and select Manage NuGet Packages…

How do you use a Foreign Key in code first approach?

To create Foreign Key, you need to use ForeignKey attribute with specifying the name of the property as parameter. You also need to specify the name of the table which is going to participate in relationship.

What is DbSet in Entity Framework?

A DbSet represents the collection of all entities in the context, or that can be queried from the database, of a given type. DbSet objects are created from a DbContext using the DbContext. Set method.


1 Answers

The ForeignKey attribute lets you define the property that will act as your foreign key if you want it to exist within your model:

[ForeignKey("CoverPaintingId")]
public virtual Painting Cover { get; set; }
public int? CoverPaintingId { get; set; }

Note you can put the attribute either on the virtual property on the foreign key - just need to specify the name of the "other one".

However, since you will have two relationships between the same set of entities, you won't be able to do this without disabling Cascading deletes on one or both of them. This can only be done using the Fluent Configuration API.

public class Gallery
{
    public int GalleryId { get; set; }

    [ForeignKey("CoverPaintingId")]
    public virtual Painting Cover { get; set; }
    public int? CoverPaintingId { get; set; }

    [ForeignKey("SliderPaintingId")]
    public virtual Painting Slider { get; set; }
    public int? SliderPaintingId { get; set; }

}

public class Painting
{
    public int PaintingId { get; set; }
}

public class MyContext : DbContext
{
    public DbSet<Gallery> Galleries { get; set; }
    public DbSet<Painting> Paintins { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Gallery>().HasOptional(g => g.Cover).WithMany().WillCascadeOnDelete(false);
        modelBuilder.Entity<Gallery>().HasOptional(g => g.Slider).WithMany().WillCascadeOnDelete(false);
    }
}

If you don't want the foreign key properties to exist in your code model, you can also configure these by using .Map(...) before the .WillCascadeOnDelete(false) part of the API instead of using ForeignKey. I prefer to use Foreign Key, but here's how the code would look if you wanted to do it this way:

public class Gallery
{
    public int GalleryId { get; set; }
    public virtual Painting Cover { get; set; }
    public virtual Painting Slider { get; set; }
}

public class Painting
{
    public int PaintingId { get; set; }
}

public class MyContext : DbContext
{
    public DbSet<Gallery> Galleries { get; set; }
    public DbSet<Painting> Paintins { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Gallery>().HasOptional(g => g.Cover).WithMany().Map(m => m.MapKey("CoverPaintingId")).WillCascadeOnDelete(false);
        modelBuilder.Entity<Gallery>().HasOptional(g => g.Slider).WithMany().Map(m => m.MapKey("SliderPaintingId")).WillCascadeOnDelete(false);
    }
}
like image 147
Richard Avatar answered Sep 30 '22 14:09

Richard