Entity Framework Migrations: Why string property ignores IsRequired"? - entity-framework

Here's my POCO
public class Game
{
public Guid Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Galaxy> Galaxies { get; set; }
}
Here's the TypeConfiguration ....
public class GameConfiguration : EntityTypeConfiguration<Game>
{
public GameConfiguration()
{
HasKey(x => x.Id);
Property(x => x.Id).HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity);
HasMany(x => x.Galaxies);
Property(x => x.Name)
.IsRequired()
.HasMaxLength(50);
}
}
My question is this... why, when this is added as a migration does the migration code not set the "Name" property as a "NOT NULL"? It also ignores the MaxLength setting too. Why is this?
CreateTable(
"dbo.Games",
c => new
{
Id = c.Guid(nullable: false),
Name = c.String(),
})
.PrimaryKey(t => t.Id);

At first glance the rest of your configuration matches what would happen by convention even if the configuration constructor never ran and the if the name property is missing that could explain it. The code that registers the configuration in the model builder is missing.
You can register the entity configuration, e.g. inside the OnModelCreated method like this:
modelBuilder.Configurations.Add(new GameConfiguration());

Related

Mapping relationships that require a navigation property only on one side

I have this model:
public class Blog
{
public int ID { get; set; }
public string Title { get; set; }
}
public class Post
{
public int ID { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public int BlogID { get; set; }
public Blog Blog { get; set; }
}
which has this configuration:
public class BlogMap : EntityTypeConfiguration<Blog>
{
public BlogMap()
{
this.ToTable("Blogs", "dbo");
this.HasKey(t => t.ID);
this.Property(t => t.ID).HasColumnName("ID");
this.Property(t => t.Title).HasColumnName("Title");
}
}
public class PostMap : EntityTypeConfiguration<Post>
{
public PostMap()
{
this.ToTable("Posts", "dbo");
this.HasKey(t => t.ID);
this.Property(t => t.ID).HasColumnName("ID");
this.Property(t => t.Title).HasColumnName("Title");
this.Property(t => t.Content).HasColumnName("Content");
this.Property(t => t.BlogID).HasColumnName("BlogID");
this.HasRequired(t => t.Blog)
.WithRequiredDependent()
.Map(???);
}
}
How do I map this?
I'm guessing that if, like a normal blog, each blog can have many posts, then maybe you need to be configuring a one-to-many relationship:
this.HasRequired(t => t.Blog)
.WithMany() // no arguments means no inverse property
.HasForeignKey(t => t.BlogID);
As an aside, EF will probably be able to infer this relationship even if you don't configure it, but explicitly configuring it is perfectly fine.

entity framework one to one with foreign key

It seems that Entity Framework have some conventions to deal with one to one relationship.
I'm using Fluent API and I need my child entity to have PK and Also FK.
Is it possible without using the [ForeignKey] attribute?
Consider the following example:
public class Principal
{
public int Id { get; set; }
public Dependent Dependent { get; set; }
}
public class Dependent
{
public int Id { get; set; }
public Principal Principal { get; set; }
}
To configure Dependent's Id property to be a foreign key to Principal's Id property with Fluent API you may choose one of the following options:
1) Starting with Entity<Dependent>:
public class AppDbContext : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Dependent>().HasRequired(d => d.Principal).WithOptional(p => p.Dependent);
}
}
2) Starting with Entity<Principal>
public class AppDbContext : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Principal>().HasOptional(p => p.Dependent).WithRequired(d => d.Principal);
}
}
They both will result in the following code first migration:
CreateTable(
"dbo.Principals",
c => new
{
Id = c.Int(nullable: false, identity: true),
})
.PrimaryKey(t => t.Id);
CreateTable(
"dbo.Dependents",
c => new
{
Id = c.Int(nullable: false),
})
.PrimaryKey(t => t.Id)
.ForeignKey("dbo.Principals", t => t.Id)
.Index(t => t.Id);
where Dependent's Id property is configured to be as a PK and a FK to Principal's Id property.

EF is creating 2 foreign keys for navigation property

The following entity configuration it creating a double foreign key for one of the navigation properties:
public User : IdentityUser
{
//public string Id { get; set; } //on base class
public virtual ICollection<Earning> Earnings { get; set; }
}
public class Earning
{
public int EarningId { get; set; }
public virtual User User { get; set; }
public string UserId { get; set; }
public virtual User Sender { get; set; }
public string SenderId { get; set; }
}
public class EarningConfiguraiton : EntityTypeConfiguration<Earning>
{
public EarningConfiguraiton()
{
this.HasRequired(e => e.User)
.WithMany(u => u.Earnings)
.HasForeignKey(e => e.UserId);
this.HasRequired(e => e.Sender)
.WithMany()
.HasForeignKey(e => e.SenderId)
.WillCascadeOnDelete(false);
}
}
However it generates 3 foreign keys for 2 navigation properties. "User_Id" is seemingly redundant. Should I remove , if so how?
CreateTable(
"dbo.Earnings",
c => new
{
EarningId = c.Int(nullable: false, identity: true),
UserId = c.String(maxLength: 128),
SenderId = c.String(maxLength: 128),
User_Id = c.String(maxLength: 128),
})
.PrimaryKey(t => t.EarningId)
.ForeignKey("dbo.AspNetUsers", t => t.SenderId)
.ForeignKey("dbo.AspNetUsers", t => t.UserId)
.ForeignKey("dbo.AspNetUsers", t => t.User_Id)
.Index(t => t.UserId)
.Index(t => t.SenderId)
.Index(t => t.User_Id);
Further more context.Users.Include(u => u.Earnings) only works with User_Id column populated, rather than UserId.
I even get this migration generated on a brand new database
There is actually a long outstanding work item on this issue with the Fluent API not correctly handling inverse navigation properties. It has been considered to be a low priority issue, and was not included in the 6.1 release due to Triage. http://entityframework.codeplex.com/workitem/1135
Ok I'm able to get past this but the bounty is still available for a better way.
Gert's comments in this answer helped me put it together.
Basically since there are 2 User entities on the Earning, EF is not going to assume which of them is bi-directional for the Earnings collection on the User.
Using [InversePropoperty] attribute works but I'm not able to configure this using Fluent Api:
Solution:
public User : IdentityUser
{
[InverseProperty("User")]
public virtual ICollection<Earning> Earnings { get; set; }
}
public class Earning
{
[InverseProperty("Earnings")]
public virtual User User { get; set; }
public virtual User Sender { get; set; }
public string SenderId { get; set; }
}
Now it generates one less foreign key. However I'm unable to configure this using Fluent Api.
public class EarningConfiguraiton : EntityTypeConfiguration<Earning>
{
public EarningConfiguraiton()
{
this.HasRequired(e => e.User)
.WithMany(u => u.EmailEarnings)
.HasForeignKey(e => e.UserId) //doesnt honor this. creates User_Id anyways
.WillCascadeOnDelete(false);
}
}
I don't know if it's a bug but bounty goes to whoever can figure it out. I'm using EF 6.1.1

WillCascadeOnDelete doesn't establish cascade delete on database

I don't know if I'm missing something obvious. We're using Entity Framework 6.0.0-rc1 in a project where the model is set up with the fluent API. Configuration of one of our entities could be:
HasMany(t => t.Entity)
.WithRequired(tc => tc.ParentEntity)
.HasForeignKey(tc => new {tc.Key1, tc.Key2})
.WillCascadeOnDelete(true);
When running this configuration, database gets created correctly, with all tables and fields. Even relationships are correctly established but not the delete cascade.
If I go to Management Studio and I inspect update/delete rules of the relationship, both are deactivated.
Thanks for your help.
With these classes:
public class Parent
{
public int ID { get; set; }
public ICollection<Child> Children { get; set; }
}
public class Child
{
public int ID { get; set; }
public int ParentID { get; set; }
public Parent Parent { get; set; }
}
Configured like this:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Parent>()
.HasMany(p => p.Children)
.WithRequired(c => c.Parent)
.HasForeignKey(c => c.ParentID)
.WillCascadeOnDelete(true);
}
Puts cascade delete on the foreign key:
public override void Up()
{
CreateTable(
"dbo.Children",
c => new
{
ID = c.Int(nullable: false, identity: true),
ParentID = c.Int(nullable: false),
})
.PrimaryKey(t => t.ID)
.ForeignKey("dbo.Parents", t => t.ParentID, cascadeDelete: true)
.Index(t => t.ParentID);
CreateTable(
"dbo.Parents",
c => new
{
ID = c.Int(nullable: false, identity: true),
})
.PrimaryKey(t => t.ID);
}

How to map parent column in EF 4.1 code first

In my project I have following DomainModel.
public class Login
{
public Guid Id { get; set; }
public Login CreatedBy {get; set; }
}
I am using fluent configuration as below:
modelBuilder.Entity<Login>()
.HasKey(x => x.Id)
.ToTable("Login");
modelBuilder.Entity<Login>()
.HasOptional(x => x.CreatedBy)
.WithMany()
.HasForeignKey(x => x.CreatedBy);
My code in repository to get all Logins data is as below:
return from d in Db.Logins.Include("CreatedBy")
select d;
When I execute the code I am getting following error:
The foreign key component 'CreatedBy' is not a declared property on type 'Login'. Verify that it has not been explicitly excluded from the model and that it is a valid primitive property.
Can anyone suggest what I am doing wrong here?
Thanks in advance
.. has not been explicitly excluded from the model and that it is a
valid primitive property
Your foreign key mapping .HasForeignKey(x => x.CreatedBy) does not use a primitive property.
public class Login
{
public Guid Id { get; set; }
public virtual Login CreatedBy {get; set; }
}
Then map it like
modelBuilder.Entity<Login>()
.HasKey(x => x.Id)
.ToTable("Login");
modelBuilder.Entity<Login>()
.HasOptional(x => x.CreatedBy)
.WithMany()
.Map(x => x.MapKey("ForeignKeyColumn"));