GR7
GR7

Reputation: 5186

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

Upvotes: 6

Views: 9791

Answers (2)

Richard
Richard

Reputation: 30618

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

Upvotes: 7

Clot
Clot

Reputation: 139

you could try to use [inverseproperty] decoration to achieve this.

Upvotes: 0

Related Questions