Code First Mapping Changes in CTP5
The information in this post is out of date.
Visit msdn.com/data/ef for the latest information on current and past releases of EF.
For Code First to a New Database see https://msdn.com/data/jj193542
For Code First to an Existing Database see https://msdn.com/data/jj200620
Code First allows you to map your .NET objects to a database schema. This blog post describes how you can accomplish many common mapping tasks using data annotation attributes and/or the fluent API and compares how you would accomplish these tasks in Entity Framework Feature CTP4 to what is now available in CTP5.
Code First mapping is about two things: using conventions and overriding those conventions with data annotation attributes and the fluent API. By default, Code First will build a mapping from your .NET objects to a database schema using conventions. When you want to override this default mapping, you can use data annotations and the fluent API. Data annotation attributes are targeted at providing a mechanism to override the most common kinds of configuration, things like setting maximum length for a property, setting a table or column name, or designating which properties are keys. There are some kinds of configuration, however, that cannot be done with the built-in data annotations: things like specifying more advanced or specific mapping scenarios such as splitting a single entity into two tables (called entity splitting), configuring inheritance hierarchies, or splitting a single table into multiple entities (called table splitting).
There were two major changes to the mapping API between CTP4 and CTP5. The first is that we moved the ability to rename columns and tables to be closer to the thing you were renaming. So, for example, there is a ToTable method to name a table on the entity configuration, and a HasColumnName method on a property configuration to rename a column. The second major change was that we removed the MapSingleType/MapHierarchy methods and replaced them with a single method called Map that can call when you are configuring an entity and when you are configuring a relationship on an entity. The map method uses a new mapping configuration class that replaces a lot of the “anonymous type” parameters in CTP4 in favor of explicit method calls. This allowed us to remove some of the utility classes such as EntityMap which were used when you wanted to rename something to a name that couldn’t be expressed as a .NET name.
Below are a number of common scenarios with examples of what the code looked like in CTP4, and how you can accomplish the same in CTP5. In many cases, the CTP4 code will not work in CTP5 as methods have been removed in favor of different methods locations.
Renaming a Table
In CTP4, you could rename a table using the MapSingleType method like in this example below:
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public Category Category { get; set; }
}
public class MyContext : DbContext
{
public DbSet<Product> Products { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// Rename a table
modelBuilder.Entity<Product>()
.MapSingleType()
.ToTable("ProductsTbl");
}
}
In CTP5, a new data annotation attribute, TableAttribute, has been added to allow you to rename a table using an attribute:
[Table("ProductsTbl")]
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public Category Category { get; set; }
}
You can also rename a table using the fluent API. In CTP5, the MapSingleType method has been removed and a new ToTable method has been added directly on the EntityTypeConfiguration class.
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public Category Category { get; set; }
}
public class MyContext : DbContext
{
public DbSet<Product> Products { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// Rename a table
modelBuilder.Entity<Product>()
.ToTable("ProductsTbl");
}
}
Renaming a Column
In CTP4, you could rename a column by using the MapSingleType (or MapHierarchy) method and specifying the properties you wanted to map by passing an anonymous type. In the example below the Product.Name property is mapped to the “ProductName” column.
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public Category Category { get; set; }
}
public class MyContext : DbContext
{
public DbSet<Product> Products { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// Rename a column
modelBuilder.Entity<Product>()
.MapSingleType(p => new {
p.Id,
ProductName = p.Name
});
}
}
In CTP5, a new data annotation attribute, ColumnAttribute, has been added to allow you to rename a column using an attribute:
public class Product
{
public int Id { get; set; }
[Column(Name="ProductName")]
public string Name { get; set; }
public Category Category { get; set; }
}
You can also rename a column using the fluent API and the HasColumnName method on the property configuration classes.
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public Category Category { get; set; }
}
public class MyContext : DbContext
{
public DbSet<Product> Products { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// Rename a column
modelBuilder.Entity<Product>()
.Property(p => p.Name)
.HasColumnName("ProductName");
}
}
Table-per-hierarchy (TPH) inheritance
Table-per-hierarchy (TPH) is a strategy for mapping a complete .NET object type hierarchy to a single database table. This is the default inheritance mapping strategy for both CTP4 and CTP5. In addition to the data from all properties for the types in the hierarchy, the table also includes a special column called the discriminator column which determines which .NET type a particular row of data is. This was accomplished in CTP4 by using the MapHierarchy method where you specified which properties were mapped to each table and what the discriminator value should be:
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public Category Category { get; set; }
}
public class DiscontionuedProduct : Product
{
public DateTime DiscontinuedOn { get; set; }
}
public class MyContext : DbContext
{
public DbSet<Product> Products { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Product>()
.MapHierarchy()
.Case<Product>(p => new {
p.Id,
p.Name,
disc = "P"
})
.Case<DiscontionuedProduct>(d => new {
d.DiscontinuedOn,
disc = "D"
});
}
}
In CTP5, the MapHierarchy method was replaced with the method Map, which takes a mapping configuration class with options on it. To specify the name of the discriminator column or the values for the discriminator, you use the “Required” method on the mapping configuration class:
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public Category Category { get; set; }
}
public class DiscontionuedProduct : Product
{
public DateTime DiscontinuedOn { get; set; }
}
public class MyContext : DbContext
{
public DbSet<Product> Products { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Product>()
.Map(mc => {
mc.Requires("disc").HasValue("P");
})
.Map<DiscontionuedProduct>(mc => {
mc.Requires("disc").HasValue("D");
});
}
Table-per type (TPT) inheritance
The Table-per-type (TPT) inheritance strategy is a popular alternative to TPH where each type in the type hierarchy is separated into its own table with columns for properties that are declared on that type. In CTP4, you would make repeated calls to the MapHierarchy method to do this where you specified which properties belong to each table/type.
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public Category Category { get; set; }
}
public class DiscontionuedProduct : Product
{
public DateTime DiscontinuedOn { get; set; }
}
public class MyContext : DbContext
{
public DbSet<Product> Products { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Product>()
.MapHierarchy(p => new {
p.Id,
p.Name
}).ToTable("Products");
modelBuilder.Entity<DiscontionuedProduct>()
.MapHierarchy(d => new {
d.Id,
d.DiscontinuedOn
}).ToTable("DiscontionuedProducts");
}
}
In CTP5, you no longer have to pass in which properties belong to each table but instead can simple say which table an entity should map to using the ToTable method:
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public Category Category { get; set; }
}
public class DiscontionuedProduct : Product
{
public DateTime DiscontinuedOn { get; set; }
}
public class MyContext : DbContext
{
public DbSet<Product> Products { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Product>()
.ToTable("Products");
modelBuilder.Entity<DiscontionuedProduct>()
.ToTable("DiscontionuedProducts");
}
Table-per concrete-type (TPC) inheritance
The Table-per concrete -type(TPC) inheritance strategy is a variation of TPT where each type in the type hierarchy is separated into its own table, but each table contains all of the properties for that type even if the properties came from a base type. In CTP4, you would make repeated calls to the MapHierarchy method to do this where you specified which properties belong to each table/type, making sure that the properties were the complete set needed by that type.
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public Category Category { get; set; }
}
public class DiscontionuedProduct : Product
{
public DateTime DiscontinuedOn { get; set; }
}
public class MyContext : DbContext
{
public DbSet<Product> Products { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Product>()
.MapHierarchy(p => new {
p.Id,
p.Name
}).ToTable("Products");
modelBuilder.Entity<DiscontionuedProduct>()
.MapHierarchy(d => new {
d.Id,
d.Name,
d.DiscontinuedOn
}).ToTable("DiscontionuedProducts");
}
}
In CTP5, just like with TPT, you no longer have to pass in which properties belong to each table. There is a helper method on the mapping configuration called MapInheritedProperties which tells Code First that you want all of the inherited properties to be mapped as part of this table as well.
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
}
public class DiscontionuedProduct : Product
{
public DateTime DiscontinuedOn { get; set; }
}
public class MyContext : DbContext
{
public DbSet<Product> Products { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Product>()
.ToTable("Products");
modelBuilder.Entity<DiscontionuedProduct>()
.Map(mc => {
mc.MapInheritedProperties();
}).ToTable("DiscontionuedProducts");
}
Entity Splitting
Entity splitting is when a single entity is mapped to columns from multiple tables. In CTP5, you could use multiple calls to MapSingleType to accomplish this. In the example below the Product class is mapped to two tables: Products, which contains Id and Name columns, and SpecialProductInfo which contains Id and the SpecialName columns.
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public string SpecialName { get; set; }
public Category Category { get; set; }
}
public class MyContext : DbContext
{
public DbSet<Product> Products { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Product>()
.MapSingleType(p => new {
p.Id,
p.Name
}).ToTable("Products");
modelBuilder.Entity<Product>()
.MapSingleType(p => new {
p.Id,
p.SpecialName
}).ToTable("SpecialProductInfo");
}
}
In CTP5, you can make use of the mapping configuration class that you access through the Map method:
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public string SpecialName { get; set; }
public Category Category { get; set; }
}
public class MyContext : DbContext
{
public DbSet<Product> Products { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Product>()
.Map(mc => {
mc.Properties(p => new {
p.Id,
p.Name
});
mc.ToTable("Products");
})
.Map(mc => {
mc.Properties(p => new {
p.Id,
p.SpecialName
});
mc.ToTable("SpecialProductInfo");
});
}
Renaming a Many-to-Many Join Table
Many to many relationships require a join table and Code First in both CTP4 and CTP5 allow you to change the name of the table and the columns of this table. In the example below for CTP4, the Products entity and the Store entity have a many to many relationship. This relationship is mapped using the relationship API methods HasMany and WithMany. Following these methods is a Map method which allows you to specify the join table name and the column names.
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<Store> SoldAt { get; set; }
}
public class Store
{
public int Id { get; set; }
public string StoreName { get; set; }
public ICollection<Product> Products { get; set; }
}
public class MyContext : DbContext
{
public DbSet<Product> Products { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Product>()
.HasMany(p => p.SoldAt)
.WithMany(s => s.Products)
.Map("ProductsAtStores",
(p, s) => new {
ProductId = p.Id,
StoreId = s.Id
});
}
}
In CTP5, the Map method has a slight change in that you interact with a mapping configuration for the many to many relationship that gives you options about what you can specify:
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<Store> SoldAt { get; set; }
}
public class Store
{
public int Id { get; set; }
public string StoreName { get; set; }
public ICollection<Product> Products { get; set; }
}
public class MyContext : DbContext
{
public DbSet<Product> Products { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Product>()
.HasMany(p => p.SoldAt)
.WithMany(s => s.Products)
.Map(mc => {
mc.ToTable("ProductsAtStores");
mc.MapLeftKey(p => p.Id, "ProductId");
mc.MapRightKey(s => s.Id, "StoreId");
});
}
Renaming a Foreign Key
There are two kinds of relationships in Entity Framework applications: those where the foreign key property is part of the entity/.NET class, and those where the foreign key is not part of the entity/.NET class. The later, where there is no foreign key property on your entity/.NET class is called an “Independent Association”, and in this case Code First will generate a foreign key column for you and place it on the appropriate table to make the relationship work.
If your entity/.NET class has a foreign key property and you want to rename it, you can do this just like you would rename any other scalar property. If your entity/.NET class is going to use an independent association, you have the option to provide a name for the foreign key column that Code First will use.
In CTP4, this was done by using a dotted syntax to access the primary key property.
public class Category
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<Product> Products { get; set; }
}
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public Category Category { get; set; }
}
public class MyContext : DbContext
{
public DbSet<Product> Products { get; set; }
public DbSet<Category> Categories { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Product>()
.MapSingleType(
p => new {
p.Id,
p.Name,
CategoryId = p.Category.Id
}
);
}
}
In CTP5, you can map the name of the generated foreign key column as part of the relationship API:
public class Category
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<Product> Products { get; set; }
}
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public Category Category { get; set; }
}
public class MyContext : DbContext
{
public DbSet<Product> Products { get; set; }
public DbSet<Category> Categories { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Product>()
.HasRequired(p => p.Category)
.WithMany(c => c.Products)
.IsIndependent()
.Map(mc => mc.MapKey(c => c.Id, "CategoryId"));
}
}
Excluding a Property from the Model
In CTP4, you could exclude a property (such as the Product.InternalCode property below) from the model by using the MapSingleType method and excluding it from the list of specified properties.
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public string InternalCode { get; set; }
}
public class MyContext : DbContext
{
public DbSet<Product> Products { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Product>()
.MapSingleType(
p => new {
p.Id,
p.Name
}
);
}
}
In CTP5, there are two ways to ignore both types and properties. The first is to use the NotMappedAttribute data annotation:
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
[NotMapped]
public string InternalCode { get; set; }
}
You can also use the fluent API in CTP5 to ignore properties using the ‘Ignore’ method:
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public string InternalCode { get; set; }
}
public class MyContext : DbContext
{
public DbSet<Product> Products { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Product>()
.Ignore(p => p.InternalCode);
}
}
We are continuing to tune this API as we progress towards the first RTM of Code First so that using it going forward helps make development as productive as possible. We’d appreciate any feedback or questions you have on the new API or how to accomplish certain mapping tasks.
Jeff Derstadt
Entity Framework Team
Comments
Anonymous
December 10, 2010
The comment has been removedAnonymous
December 12, 2010
This is reply to blogs.msdn.com/.../ef-feature-ctp5-fluent-api-samples.aspx Original problem : blogs.msdn.com/.../ef-feature-ctp5-fluent-api-samples.aspx Thank for you reply Jeff, but you code did'nt solve the problem :( The problem that i can't set name for "KEY" column on inherited (in my example "Event") table. In your case EF make wrong sql command : select bla,bla,bla from BaseEvent as Extent1 LEFT JOIN (SELECT [Extent2].[bev_ID] AS [bev_ID], --- ERROR HERE - must be ev_bev_ID [Extent2].[ev_Date] AS [ev_Date], cast(1 as bit) AS [C1] FROM [dbo].[Event] AS [Extent2] ) AS [Project1] ON [Extent1].[bev_ID] = [Project1].[bev_ID] When i tried add code that this column was rightly mapped modelBuilder.Entity<Event>() .Property(b => b.ID).HasColumnName("ev_bev_ID"); EF raise System.InvalidOperationException : The configured property 'ID' is not a declared property on the entity 'Event'. Verify that it has not been explicitly excluded from the model and that it is a valid primitive property. In CTP4 this problem did'nt exists. Thank you. AlexAnonymous
December 14, 2010
Regarding the last example with excluding properties, I hope you also fully support the include/opt-in style of explicitly mapping properties in addition to the exclude/opt-out style mapping. In some cases this can make more sense.Anonymous
December 19, 2010
I tried implementing your entity splitting example (using only the Property class without a category) but, upon first run, I got an exception: A value shared across entities or associations is generated in more than one location. Check that mapping does not split an EntityKey to multiple store-generated columns. InnerException: An item with the same key has already been added. I got this in the Seed method override of my derivation of DropCreateDatabaseIfModelChanges where I add a single product, specifying the three properties: context.Products.Add(new Product { Id = 1, Name = "Pumpkin", SpecialName = "Pie" }); context.SaveChanges(); It created the database correctly (a Products table with Id and Name columns and a SpecialProductInfo table with Id and SpecialName columns) but didn't add the seed data since the exception occurred on the SaveChanges invocation.Anonymous
December 22, 2010
I would like to have collections be protected / private and exposing them as enumerables in order to use accessor methods to add remove objects from them. Can this be done and how? Instead of: public virtual ICollection<Order> Orders { get; set; } Replace with: private virtual IList<Order> orders = new List<Order>(); public virtual IEnumerable<Order> Orders { get { return orders; } } public virtual void AddOrder(Order order) { // body removed for brevity } public virtual void RemoveOrder(Order order) { // body removed for brevity } If such a mapping is possible, how would that code look? Thanks in advance!Anonymous
December 23, 2010
Sorry, in advance, 'cause I don't know if this is the right place to put my question. Imagine you have a lot of products (a huge amount of them, hundreds of thousands). There could be only a few categories, so each category could have thousands of products. Imagine I need (in the client application) to show a TreeView with each category and for each node I want to display: categoryName+numberOfProducts . I know using .Include("Products") in the query for Categories, I could do (in the client) something like: text = category.Name + category.Products.Count(); but this will means I need to send to the client a lot of objects, just for showing their amount in the parent object. Is there any way to extend EF Category object for adding a custom property that does this job (allowing queries over it)??? This way, the Category object will have a new property (NumOfProducts) that can be used in the client side (should be queriable in the way: Categories.Where(c=>c.NumOfProducts>100) ), and the client doesn't need to get all the referenced objects for showing just their amount within the parent. Does it make sense? could you please write a sample on how to fix this?Anonymous
December 28, 2010
Will there be mappings to indicate an entity is readonly or update only? Also, will you be able to map to an enum with Code First?Anonymous
December 29, 2010
One inconsistency that I noticed is with the Table and Column attributes. Table has a default parameter which is the name of the table. Column doesn't have a default parameter. Instead you have to specify the name using the Name named parameter. It would be nice if the two were consistent.Anonymous
December 29, 2010
Also, there should be an attribute that allows you to specify the name of the database that the context is associated with without having to use the fluent API. Either that, or it would be nice if the conventions did a little more checking. For example, I have a database called Forms, I want my DbContext to be called FormsContext, not Forms. There should be an easy way to do that. It would also be nice if it were possible to easily turn off the pluralization for table names. i.e. If I have a class called Person, I want to table name to be Person also. I don't want it to be People. I know you can use an attribute to specify this on a table by table basis, but, it would be good if it were possible to easily turn that off globally. Personally, I find the pluralization a bit annoying. I like having the names be singular instead because it seems more consistent and matches up with the class names exactly. Also, I think it makes it more consistent for link tables. e.g. Say a person can have many roles and a role can have many people. I like having my tables setup like Person, PersonRole, Role where the link table is always the two table names combined. If you use pluralization it doesn't look right.Anonymous
December 29, 2010
The comment has been removedAnonymous
December 29, 2010
Nevermind what I said about being able to specify the database name easily. I found another blog post that explains how to do it. You can specify it using a constructor in DbContext and there are a few other simple solutions. One thing I'm wondering though, is whether there will be additional attributes included in the RTM for specifying things like table-per-type inheritance? The fluent API is simple enough, but, it seems like one shouldn't have to use the fluent API at all. You should be able to specify everything using nothing more than attributes IMHO.Anonymous
December 30, 2010
@Drew Entity Framework does not yet support allowing collections to be IEnumerable with Add/Remove methods. This is something we'd like to support in a future release though.Anonymous
December 30, 2010
@NNZZ What is the type of "e.property"? We've had some bugs if this is not a scalar property so maybe you are running into this?Anonymous
December 30, 2010
@Jon M Thanks for the feedback about the attributes. ColumnAttribute doesn't have that constructor because sometimes people just want to use the attribute to do column ordering. Having mutliple constructors would help here. Our hope is that by RC/RTM time, we'll have a very concise story for how to turn on/off conventions and how to easily add new ones so you or others can make attributes that have full parity with the fluent API, but that is not our priority at the moment.Anonymous
December 30, 2010
I'm wondering if it's possible to do entity splitting in the following scenario. class {string Id; string ItemId; string ItemName, ItemDisplayName} MainTable {Id, ItemId, ItemName}, OptionalTable{ ItemId, ItemDisplayName} Some of the items have optional display names that need to be used if present. In SQL term, it's MainTable left join OptionalTable on ItemId. Id ItemId ItemName ItemDisplayName 1 aaa NameA 2 bbb NameB DisplayNameB 3 ccc NameC How do I map the class to the two underlying table? ThanksAnonymous
December 30, 2010
@Jeff e.Property is just a string. It is defined in a base type, so could that be the issue?Anonymous
January 02, 2011
Hello, It is possible to do conditional horizontal entity splitting with code first, as we do it within MSL : .....mapping <Condition Name="IsPriority" Value="false" /> .....mappingAnonymous
January 08, 2011
It is possible to do conditional horizontal entity splitting with code first, as we do it within MSL ? .....mapping <Condition Name="IsPriority" Value="false" /> .....mappingAnonymous
January 23, 2011
Excellent Article, If I understand it correctly, In EF CTP5, there no need to specify a database (or connection, no need for edmx). Can I get a copy of the code. TIA YazAnonymous
January 28, 2011
Excellent article for a great product! :) I have a question though. I have a User class and an Address class. The user can have multiple addresses, but I also want to hold a reference to the DefaultAddress of the user. Currently, I have it mapped as follows: public class User { public int ID { get; set; } //other properties public virtual ICollection<Address> Addresses { get; set; } public virtual Address DefaultAddress { get; set; } } public class Address { public int ID { get; set; } public string Name { get; set; } public string Details { get; set; } public virtual City City { get; set; } } First, is that the right way of doing the whole thing? Second, how can I rename attribute/column being generated in the User class which references the default address? (currently it is being mapped as AddressID). Thanks in advance, KassemAnonymous
February 17, 2011
How to map overrider property? I have a base class as follows: public class TestMessage { public virtual string Module { get; set; } } a derived class as follows: public class TestAlarmMessage : TestMessage { private string mModule = string.Empty; public int AlarmID { get; set; } public override string Module { get { return "testmodule"; } set { mModule = value; } } public string Name { get; set; } public string Description { get; set; } public DateTime CreateTime { get; set; } } the map code as follows: modelBuilder.Entity<TestAlarmMessage> ( ).Property ( am => am.Module ).HasColumnName ( "ModuleName" ); the exception as follow: The configured property 'Module' is not a declared property on the entity 'TestAlarmMessage'. Verify that it has not been explicitly excluded from the model and that it is a valid primitive property.Anonymous
February 28, 2011
Is there a way to set custom names, how are they gonna be generated in the database, for Primary Keys, Foreign Kyes etc.?Anonymous
March 01, 2011
HasColumnName is NOT consistently working. Please have a look at my configuration below. public class ClientConfiguration : EntityTypeConfiguration<Client> { public ClientConfiguration() { this.Property(c => c.DateOfBirth).HasColumnName("DateOfBirth"); this.Property(c => c.HomePhone).HasColumnName("HomePhone"); this.ToTable("Client"); } } The DateOfBirth is being created in the table as "DateOfBirth1" but the HomePhone is created as "HomePhone". The difference is that the DateOfBirth has a suffix of "1".Anonymous
March 11, 2011
When I do an UpdateModel() on a collection of child object with CTP5 I get the following error? The operation failed: The relationship could not be changed because one or more of the foreign-key properties is non-nullable. When a change is made to a relationship, the related foreign-key property is set to a null value. If the foreign-key does not support null values, a new relationship must be defined, the foreign-key property must be assigned another non-null value, or the unrelated object must be deleted. I've tried not changing any of the values in the collection and I still get this error? I seems to be deleting the references and therefore entity things I'm trying to delete these objects? Are there any work arounds for this issue? Here is a link to my stackoverflow question regarding this issue: stackoverflow.com/.../ctp5-ef-code-first-question Any help would be greatly appreciated. KyleAnonymous
March 16, 2011
Thank very much for this great post Jeff. I love EF-CF CTP5 but I have a specific need and I don't know if it is possible. Thanks very much in advance. Alvaro //------------------------------------------------------- // Question //------------------------------------------------------- // There is any way to simply say: "MapDerivedClasses" // without setting explicit map for each derived type? // For instance: // modelBuilder.Entity<Person>() // .MapDerivedClasses() // <-- Simple way using base type and only its properties. // .ToTable("Person"); //------------------------------------------------------- //------------------------------------------------------ /// <summary> /// Sample form metadata problem with base class. /// </summary> [Table("Person")] public class Person { [Key] [DatabaseGenerated(DatabaseGenerationOption.Identity)] public int Id { get; set; } [Required] [MaxLength(150)] public string Name { get; set; } } //--------------------------------- // Different kind of people public class Citizen : Person { } public class Student : Person { } //--------------------------------- public class MyContext : DbContext { public DbSet<Person> People { get; set; } } /// <summary> /// What I need? /// </summary> class Program { static void Main(string[] args) { using (MyContext ctx = new MyContext()) { //------------------------------------------------------- // Working with base class. //------------------------------------------------------- Person person = new Person() { Name = "Person1" }; ctx.People.Add(person); //This is OK. ctx.SaveChanges(); //------------------------------------------------------- // Working with derived types (Citizen|Student|etc...). //------------------------------------------------------- Student student = new Student() { Name = "Student1" }; //************************** // WARNING! It does not work! //************************** ctx.SaveChanges(); //------------------------------------------------------- // Question //------------------------------------------------------- // There is any way to simply say: "MapDerivedClasses"? // For instance: // modelBuilder.Entity<Person>() // .MapDerivedClasses() // <-- Simple way using base type and only its properties. // .ToTable("Person"); //------------------------------------------------------- // I understand that I could set the mapping for derived // classes as is shown: //protected override void OnModelCreating(ModelBuilder modelBuilder) //{ // modelBuilder.Entity<Product>() // .ToTable("Products"); // modelBuilder.Entity<DiscontionuedProduct>() // .Map(mc => { // mc.MapInheritedProperties(); // }).ToTable("DiscontionuedProducts"); //} } } } //------------------------------------------------------------------------Anonymous
March 16, 2011
The comment has been removedAnonymous
December 09, 2012
How to call the one to one mapping..i.e controller for the one to one mapping to display the related data.