Entity Framework foriegn key to existing table column - entity-framework

I have the following table in my database
Company
resourceId (uniqueidentifier)
name (nvarchar(50))
I have the following User entity in my application
public class ApplicationUser : IdentityUser
{
public String FirstName { get; set; }
public String Surname { get; set; }
public Guid CompanyId { get; set; }
}
and a configuration class
public class ApplicationUserMap : EntityTypeConfiguration<ApplicationUser>
{
public ApplicationUserMap()
{
}
}
Using fluentapi how can I map a foriegn key from CompanyId in Application user to my existing table resourceid?

You cannot do that if Company is not included in your model.
You can only create the relationship in the DB using an standard T-SQL sentence, in the DB initialization (Seed()) or in a customized migration (if you're using migrations).
The command would loook like this:
alter table ApplicationUser
add constraint App_Company_FK FOREIGN KEY (CompanyId) references Company(CompanyId)
To run it in the Seed method, override the inhertied Seed() method, and use any of the overloads of Database.ExecuteSqlCommand:
context.Database.ExecuteSqlCommand( ... );

Related

Adding a new relation to existing database using entity framework

Given a database with a table A. I want to create a table B and add a one-to-may relation between A and B with a required foreign key.
For example suppose that have an existing table 'Users' and then we want to add 'Roles' to the existing users.
The code first definition of those entities is as follows:
public class User
{
public Id UserId { get; set; }
public string Email { get; set; }
public string UserName => Email;
public Roles Role { get; set; }
public int? RoleId { get; set; }
}
public class Roles
{
public string RoleName { get; set; }
public int RoleId { get; set; };
public ICollection<User> GetUsers { get; set; }
}
The Configure Method for the Users using Fluent API is as follows:
public void Configure(EntityTypeBuilder<User> builder)
{
builder.ToTable("User");
builder.HasKey(t => t.UserId );
builder.Property(t => t.UserId ).ValueGeneratedOnAdd();
builder.HasOne(dt => dt.Role)
.WithMany(d => d.GetUsers)
.HasForeignKey(dt => dt.RoleId)
.HasConstraintName("ForeignKey_UserRole")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
}
Trying to run the migration I got this error message:
'The ALTER TABLE statement conflicted with the FOREIGN KEY constraint'
By splitting this migration in two migrations and seeding the data between the them allowed me to build the new database:
The first one remove the constrain IsRequired on the Fluent APi definition of the User entity and allowing null value for the foreign key RoleId.
Then Seed the database
Add the second and last migration to enable the constrain of the required foreign key RoleID in the User entity and removing the allows null on the foreign key.
My question is related to if there is an strategy that allows to add a new relation using code first approach with a required foreign key using only one migration?
Thank you
Francisco

How to add a foreign key reference to ASP.Net MVC 5 Identity?

I have a new ASP.NET MVC 5.1 project using the ASP.Net Identity.
It seems reliable and promise, but today i spend almost 9 hours to do a simple things if using SQL.
My problem is, i cannot create a table via CodeFirst with foreign key reference to the default AspNetUsers table.
For example:
I have create a table named - Address
public class Address
{
[Key]
public string UserId { get; set; }
public string MyAddress { get; set; }
}
But how can i create a foreign key reference to AspNetUsers?
I try replace the property above by
public IdentityUser MyAddress { get; set; }
// Or
public virtual IdentityUser MyAddress { get; set; }
// Or
public virtual ApplicationUser MyAddress { get; set; }
But all of them still show error:
One or more validation errors were detected during model generation:
MiaPos.Models.IdentityUserLogin: : EntityType 'IdentityUserLogin' has no key defined. Define the key for this EntityType.
MiaPos.Models.IdentityUserRole: : EntityType 'IdentityUserRole' has no key defined. Define the key for this EntityType.
IdentityUserLogins: EntityType: EntitySet 'IdentityUserLogins' is based on type 'IdentityUserLogin' that has no keys defined.
IdentityUserRoles: EntityType: EntitySet 'IdentityUserRoles' is based on type 'IdentityUserRole' that has no keys defined.
I also try override the OnModelCreating from this post
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<IdentityUserLogin>().HasKey<string>(l => l.UserId);
modelBuilder.Entity<IdentityRole>().HasKey<string>(r => r.Id);
modelBuilder.Entity<IdentityUserRole>().HasKey(r => new { r.RoleId, r.UserId });
}
But when i run Add-Migration, it create the IdentityUserLogin, IdentityRole, IdentityUserRole tables and it duplicate, just the prefix is different. (AspNet<->Identity)
Finally i do it by SQL in 10 seconds, but i just want to know why i cannot do in CodeFirst?
And why so hard to do a such things from Microsoft 2014 New Technology.
You can do like this. because sometime you may need 1-1 connection
public class AnotherTable
{
[Key]
public string UserId { get; set; }
[ForeignKey("UserId")]
public virtual ApplicationUser User { get; set; }
}
Thanks you Gábor Plesz for comment above.
I found the solution.
The ApplicationUser class who inherit IdentityUser (which create AspNetUsers table) should create a ICollection property of the child class (child table).
e.g.
public virtual ICollection<ToDo> ToDoes { get; set; }
So the ToDo class can be reference to ApplicationUser
Highly recommend have a look the sample as Gábor Plesz said.
If you really wanna create a table named Address instead of creating a property named Address to generated as a column into AspNetUsers table do the following (obs: in this case i am assuming that a user can have many address):
At your Address class:
public class Address
{
public string MyAddress { get; set; }
// referencing the AspNetUsers table ( ApplicationUser.cs)
public string UserId { get; set; }
public virtual ApplicationUser User { get; set; }
}
Your ApplicationUser Class:
public virtual ICollection<Address> Addresses { get; set; }
Within your DBContext in OnModelCreating method do the following ( fluent API ):
builder.Entity<Address>()
.HasOne(c => c.User)
.WithMany(x => x.Addresses)
.HasForeignKey(f => f.UserId)
.HasConstraintName("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
OBS: Don´t forget adding above the OnModelCreating method this line of code:
public DbSet<Address> Addresses { get; set; }
After it run those commands within your Package Manager Console:
Add-Migrations UserAddress
and after:
Update-Database.
But, if you wanna just inclued a new property to the AspNet Users just create at your ApplicationUser.cs file/class this property:
public class ApplicationUser : IdentityUser
{
public string Address { get; set; }
}
and run the same commands for your PMC:
Add-Migration UserAddress
after:
Update-Database
Hope this helps!

How do I override entity framework code first convention for creating a foreign key

I have a property on my items class called vend_id which of course EF thinks is a foreign key to the vendor table. It actually should be a foreign key in the database but for reasons unknown to me the designers of the db chose not to make it a foreign key.
I am using EF to create a copy of the db schema on the local machine. When EF creates the database I want to tell it not to create a foreign key on the vend_id column. How do I do that? Ideally I do not want to rename the property because there are several such instances in my db and it just makes it confusing.
Thank you,
Sam
You can't have a navigation property to a Vendor entity in your Item entity class if the Items table does not have a foreign key to table Vendor. If you did not specify a navigation property in entity class Item, EF would not infer that vend_id is a foreign key.
Update:
Unable to reproduce with the following:
[Table("EntityA")]
public partial class EntityA
{
public int Id { get; set; }
public Nullable<int> EntityBId { get; set; }
public string Description { get; set; }
[ForeignKey( "EntityBId" )]
public virtual EntityB EntityB { get; set; }
// this is not created as a FK
// nor does EntityCId cause a FK
public int EntityC_Id { get; set; }
}
[Table("EntityC")]
public class EntityC
{
public EntityC()
{
EntitiesD = new HashSet<EntityD>();
}
public int EntityCId { get; set; }
public string Name { get; set; }
public virtual ICollection<EntityD> EntitiesD { get; set; }
}

How to correctly build EF5 Code-first model with two or more lists that relate to the same child table?

I have the following models:
public class SomeForm
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public IList<FacilityContactInformation> OriginatingFacilities { get; set; }
public IList<FacilityContactInformation> DestinationFacilities { get; set; }
}
public class FacilityContactInformation
{
public FacilityContactInformation()
{
Id = -1;
}
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[MaxLength(50)]
public string Owner { get; set; }
}
I am using automatic migrations to gen and re-gen the database schema.
This generates the error "Foreign key 'FK_dbo.FacilityContactInformations_dbo.SomeForm_SomeForm_Id ' references invalid column 'SomeForm_Id' in referencing table 'FacilityContactInformations'.
Could not create constraint. See previous errors.
I suspect the root cause is that EF tries to generate a FK FK_dbo.FacilityContactInformations_dbo.SomeForm_SomeForm_Id for both lists
Is there any way to keep using automatic migrations, but get this to generate a FK that works? It would seem like the FK should include the list name and generate two properties on FacilityContactInformations OR should generate an intermediate table to join on.
When you have 2 navigational properties that link to the same class, you should override OnModelCreating method of your dbcontext class. Then add this code into the OnModelCreating:
modelBuilder.Entity<SomeForm>
.Hasmany<FacilityContactInformation>(x => x.OriginatingFacilities);
modelBuilder.Entity<SomeForm>
.Hasmany<FacilityContactInformation>(x => x.DestinationFacilities);
This is because EF cannot determine the correct keys if the nav. prop. link to the same class.

Entity Framework code first: POCO's inheritance

I have an issue when defining some POCO objects (entities) in entity framework code first 4. I have a main entity, let's say Entity_A, which has only a property, only the ID (primary key). The rest of entities (Entity_B in this example) inherits from it (childs) except some of them (Entity_C) that inherits from another entity (from Entity_B, not from Entity_A). For example:
public class Entity_A
{
public virtual Guid ID { get; set; }
}
// Entity_B has not primary key defined within as it inherits from Entity_A
public class Entity_B : Entity_A
{
public virtual string propertyB1 { get; set; }
public virtual string propertyB2 { get; set; }
public virtual string propertyB3 { get; set; }
}
// Entity_C has not primary key defined within as it inherits from Entity_A through Entity_B
public class Entity_C : Entity_B
{
public virtual string propertyC1 { get; set; }
public virtual string propertyC2 { get; set; }
public virtual string propertyC3 { get; set; }
}
so after executing it, tables for Entity_A, Entity_B, Entity_C are generated automatically but only table for Entity_A and Entity_B are correct but not for Entity_C:
Table Entity_A has fields:
-ID
which is correct.
Table Entity_B has fields:
-ID
-propertyB1
-propertyB2
-propertyB3
which is correct as well.
Table Entity_C has fields:
-ID
-propertyC1
-propertyC2
-propertyC3
which is not correct for me, as for Entity_C I expect the following fields:
-ID
-propertyB1
-propertyB2
-propertyB3
-propertyC1
-propertyC2
-propertyC3
What am I doing wrong? Is not entity framework code first (version 4.1) supporting inheritance at all?
Thanks in advance.
Try adding a record to Entity_C, you will notice that a record is added to Entity_B and Entity_A as well.
This is table inheritance. An Entity_C is an Entity_B, so why duplicate the rows?