locked
Mapping properties in CTP5 RRS feed

  • Question

  • I'm upgrading some code in OnModelCreating from CTP 4 to CTP 5 that looks like this:

    modelBuilder.Entity<TradeName>().MapSingleType(m => new
          {
            FIELD_1_ID = m.Id,
            FIELD_2_NAME = m.Name
          }).ToTable("FUNKY_TABLE_NAME");
    
    

    .MapSingleType() is gone with CTP 5, what is the equivalent method? I've been testing .Map(), but can't find a way to map a block of properties like in CTP 4.

    Chris

    • Edited by Chris Sutton Tuesday, December 7, 2010 8:49 PM fix code formatting
    Tuesday, December 7, 2010 8:47 PM

Answers

  • Using HasColumnName is the way to set a column name using the fluent API as of CTP5:

     

    modelBuilder.Entity<TradeName>().Property(p => p.Id).HasColumnName("FIELD_1_ID");

     

    There is also a ColumnAttribute data annotation that can be used to set a column name.

     

    [Column(Name = "FIELD_2_NAME")]

    public string Name { get; set; }

     

    MapSingleType caused a lot of confusion in CTP4 which is why we spent time re-designing it.  However, the ability to specify the column names for a lot of properties in a block is something that we will consider re-introducing for RTM.  In particular, we will consider making this work:

     

                modelBuilder.Entity<TradeName>()

                    .Map(m => m.Properties(p => new

                                                    {

                                                        FIELD_1_ID = p.Id,

                                                        FIELD_2_NAME = p.Name

                                                    }))

                    .ToTable("FUNKY_TABLE_NAME");

     

    Note that if we do this then there will still be some column names that can’t be mapped in this way, notably those with invalid characters in the property names for the anonymous type.  In those cases you would have to use HasColumnName or ColumnAttribute.

     

    Thanks,

    Arthur

     

     

    Tuesday, December 7, 2010 11:43 PM
    Moderator

All replies

  • I've tried this (to no avail)

     

    modelBuilder.Entity<TradeName>().Map(m => m.Properties(p => new
       {
        FIELD_1_ID = m.Id,
        FIELD_2_NAME = m.Name
       })).ToTable("FUNKY_TABLE_NAME");

     

    This seems to work but is messy:

     

    var entryConfig = modelBuilder.Entity<CalendarEvent>();

    entryConfig.HasKey(p => p.Id);

    entryConfig.Property(p => p.Id).HasColumnName("FIELD_1_ID");

    entryConfig.Property(p => p.Name).HasColumnName("FIELD_2_NAME ");

    entryConfig.Map( m => m.ToTable("FUNKY_TABLE_NAME"));

    Tuesday, December 7, 2010 10:43 PM
  • Using HasColumnName is the way to set a column name using the fluent API as of CTP5:

     

    modelBuilder.Entity<TradeName>().Property(p => p.Id).HasColumnName("FIELD_1_ID");

     

    There is also a ColumnAttribute data annotation that can be used to set a column name.

     

    [Column(Name = "FIELD_2_NAME")]

    public string Name { get; set; }

     

    MapSingleType caused a lot of confusion in CTP4 which is why we spent time re-designing it.  However, the ability to specify the column names for a lot of properties in a block is something that we will consider re-introducing for RTM.  In particular, we will consider making this work:

     

                modelBuilder.Entity<TradeName>()

                    .Map(m => m.Properties(p => new

                                                    {

                                                        FIELD_1_ID = p.Id,

                                                        FIELD_2_NAME = p.Name

                                                    }))

                    .ToTable("FUNKY_TABLE_NAME");

     

    Note that if we do this then there will still be some column names that can’t be mapped in this way, notably those with invalid characters in the property names for the anonymous type.  In those cases you would have to use HasColumnName or ColumnAttribute.

     

    Thanks,

    Arthur

     

     

    Tuesday, December 7, 2010 11:43 PM
    Moderator
  • Arthur,

    Thanks for the explanation. The MapSingleType name might have been confusing, but the simple anonymous block mapping was really handy for cleaning up tables with lots of messy names.

    I see what you are saying about columns with invalid characters, that you would have to use the attribute or .HasColumnName anyway. I don't see any harm in having 3 ways to accomplish the task.

    I went with .Property().HasColumnName() and that worked fine for upgrading my current project.

    Thanks,

    Chris

     

     

    Wednesday, December 8, 2010 12:29 AM
  • For what it is worth, here is a simple VS regex to switch around the old property mapping to the new method:

    Find what:  {[^ ]*} = [^\.]*\.{[^,]*},*$

    Replace With:  config.Property(p => p.\2).HasColumnName("\1");

    Use: Regular Expressions

     

     new

                       {

                           RadarId = entity.Id,

                           RadarTitle = entity.Title,

                           RadarCreateDate = entity.CreatedDate,

                       })

    -> replace all, remove the "new {}" and add a "var config = ModelBuilder.Entity<YourType>();" and then use the new property assignments:

     

     

    config.Property(p => p.Id).HasColumnName("RadarId");

    config.Property(p => p.Title).HasColumnName("RadarTitle");

    config.Property(p => p.CreatedDate).HasColumnName("RadarCreateDate");

     

     

    Wednesday, December 8, 2010 1:04 PM
  • Hi Arthur,

    Personally, I prefer the CTP4 approach - it's more concise. In my case, I end up mapping every column because we have a large, shared legacy database which mostly uses underscores for field names, and with very little consistency to boot. I don't want to use the [Column("...")] attribute because I would need my entities assembly to take a dependency upon the EF assembly for that, besides, the column name is *definitely* a storage concern rather than an entity concern. At the current time this leaves me dependent upon the HasColumnName("...") method for mapping my entities, which is a bit sucky.

    I'm pleased to hear you say that you're considering making m.Properties(p => new { ... }) work for RTM. I was quite disappointed when I realised it doesn't work in CTP5. It's not as clear as the CTP4 syntax, but it's a compromise I'd be willing to make in order to avoid repeating Property(p => p.Xxx).HasColumnName("x_x_x") for every poorly named field on my entities (i.e. all of them).

    I consider the funky named fields to be a bit of an edge case. Even in my nasty old database, there aren't any fields that are invalid C# identifiers.

    Thanks for EF CF though. With the exception if this matter, I think CTP5 is shaping up to be very nice indeed.

     

    Thanks,
    Damian.

    Saturday, February 5, 2011 8:28 PM