As an example I had following existing table, which i cannot change
Contacts - [ID, Name, Age] (Primary Key: ID)
No i want to extend the functionality using following extension table
Details - [ID, Address, Phone] (Primary Key:ID, Foreign Key: ID)
Note that Details.Id is primary key as well as foreign key (referencing Contacts.Id)
My domain model is
Contact
{
public int Id {get;set;}
public string Name {get;set;}
public int Age {get;set;}
public Details Details {get;set;}
}
Details
{
public int Id {get;set;}
public string Address {get;set;}
public string Phone {get;set;}
}
How do i write mapping for this in entity framework 6
You can use composite key this way:
public class Details
{
[Key, ForeignKey("Contact")]
public int Id { get; set; }
public string Address { get; set; }
public string Phone { get; set; }
public Contact Contact { get; set; }
}
public class Contact
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public Details Details { get; set; }
}
Now Details's ID is a primary key as well as foreign key
Related
Model:
public class Address
{
[Key]
public long AddressId { get; set; }
public string Street { get; set; }
public string Town { get; set; }
public string State { get; set; }
public string Country { get; set; }
}
public class User
{
[Key]
public long UserId { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public virtual List<Address> Addresses { get; set; }
}
DBContext:
public class DataModelContext : DbContext
{
public DbSet<Address> Addresses { get; set; }
public DbSet<User> Users{ get; set; }
}
Using above code its creating this schema for DB.
Addresses Users
----------- -------
AddressId(PK) UserId(PK)
Street UserName
Town Password
State
Country
User_UserId(FK)
Now i want to access User_UserId from Addresses table, but it not showing any property there. Its giving error "Address does not contain a definition for User_UserId.....
using (var db = new DataModelContext())
{
db.Addresses.Select(x=>x.User_UserId).ToList();
}
Use Foreign-Key Association instead of independant association while creating models. It means that, you must include a foreign key property in your model alongside with a corresponding Navigational Property. For example:
public class Address
{
...
public int UserId {get; set;} //Foreign-Key property
[ForeignKey("UserId")]
public virtual User User { get; set; } // Navigational Property
...
}
Read this article for more information.
I am trying to create a relationship between two tables but keep getting the following error:
The ForeignKeyAttribute on property 'CallLogId' on type
'Ylp.Web.ParkingApi.DataLayer.Entities.ApiCallLogDetailEntity' is not
valid. The navigation property 'ApiCallLog' was not found on the
dependent type
'Ylp.Web.ParkingApi.DataLayer.Entities.ApiCallLogDetailEntity'. The
Name value should be a valid navigation property name.
DbContextMapping:
modelBuilder.Entity<ApiCallLogDetailEntity>()
.HasRequired<ApiCallLogEntity>(p => p.ApiCallLog);
Primary table:
[Table("ApiCallLog")]
public class ApiCallLogEntity
{
[Key, Column(Order = 0)]
public string CallLogId { get; set; }
[Key, Column(Order = 1)]
public string UserId { get; set; }
[Required]
public string CallFilterId { get; set; }
[Required]
public DateTime LastUpdated { get; set; }
[Required]
public int Count { get; set; }
public virtual ICollection<ApiCallLogDetailEntity> Details { get; set; }
}
foreign table:
[Table("ApiCallLogDetail")]
public class ApiCallLogDetailEntity
{
[ForeignKey("ApiCallLog")]
public string CallLogId { get; set; }
[Required]
public string PrametersHashCode { get; set; }
[Required]
public DateTime LastUpdated { get; set; }
public ApiCallLogEntity ApiCallLog { get;}
}
The foreign key must refer to the whole primary key of the parent table. In your parent table you have a composite primary key which includes CallLogId and UserId. The message is confusing, but this can be part of the error. Is it really necessary to include the UserId in the PK?
Another error is that you have not defined the PK in the dependent table. If the UserId is also necessary on the PK, include it in the dependent table, and make it part of the FK.
I am using EF 6.1.1.
I am unable to figure out how to create One-to-One relationship between two classes/tables with both entities have their owns PKs. I originally posted question link but could not get much help on it OR i am not able to get it. So, here i am putting my question in simple way.
Appreciate if someone can share thoughts on it.
My Requirement:
I would like create One-To-One relationship between Principle and Dependant with 'Id' from Principle class acts as Foreign Key in dependant class.
Principle Class
public class Student
{
public string FullName {get; set;}
}
Dependant Class
public class StudentReport
{
public string RollNumber { get; set; }
public string StudentType { get; set; }
}
Add PKs – EF requires this:
public class Student
{
public int Id { get; set; }
public string FullName { get; set; }
}
public class StudentReport
{
public int Id { get; set; }
public string RollNumber { get; set; }
public string StudentType { get; set; }
}
Note that EF 5 and later supports naming conventions: Id indicates a primary key. Alternately, it also supports the name of the class followed by "Id", so the above keys could have been StudentId for Student and StudentReportId for StudentReport, if you wished.
Add the foreign relation as a navigation property to at least one of the tables – in this case, you stated that StudentReport is the dependent, so let's add it to that one:
public class Student
{
public int Id { get; set; }
public string FullName { get; set; }
}
public class StudentReport
{
public int Id { get; set; }
public string RollNumber { get; set; }
public string StudentType { get; set; }
public Student Student { get; set; }
}
Again – by naming convention – EF determines that a single Student property on StudentReport indicates that this is a navigational property associated with a foreign key. (By defining only the Student property, but no foreign key property, you are indicating that you don't care what EF names the associated FK ... basically, you're indicating you'll always access the related Student via the property.)
If you did care about the name of the FK property, you could add it:
public class Student
{
public int Id { get; set; }
public string FullName { get; set; }
}
public class StudentReport
{
public int Id { get; set; }
public string RollNumber { get; set; }
public string StudentType { get; set; }
public int StudentId { get; set; }
public Student Student { get; set; }
}
Again – by naming convention – EF determines that StudentId is the FK associated with the Student property because it has the class name, "Student", followed by "Id".
All of this, so far, has been using conventions as defined in Entity Framework Code First Conventions, but Data Annotations are also an option, if you wish:
public class Student
{
[Key]
public int Id { get; set; }
public string FullName { get; set; }
}
public class StudentReport
{
[Key]
public int Id { get; set; }
public string RollNumber { get; set; }
public string StudentType { get; set; }
[ForeignKey("Student")]
public int StudentId { get; set; }
public Student Student { get; set; }
}
Doing this is actually a good idea, because it makes clearer your intent to other programmers that might not be aware of EF Conventions – but can easily infer them from simply looking at EF Data Annotations – and is still less cumbersome than Fluent API.
UPDATE
I just realized, I left this as a one-to-many, with enforcement of the one-to-one relationship being left to do in the code using this model. To enforce the one-to-one in the model, you could add a navigation property to the Student class going the other way:
public class Student
{
public int Id { get; set; }
public string FullName { get; set; }
public StudentReport StudentReport { get; set; }
}
public class StudentReport
{
public int Id { get; set; }
public string RollNumber { get; set; }
public string StudentType { get; set; }
public Student Student { get; set; }
}
However, that's going to break, because EF doesn't know which entity to insert first on an add. To indicate which is dependent, you have to specific that the dependent class' PK is the FK to the principal class (this enforces one-to-one because – in order for a Student/StudentReport pair to be associated – their Id properties must be the exact same value):
public class Student
{
public int Id { get; set; }
public string FullName { get; set; }
public StudentReport StudentReport { get; set; }
}
public class StudentReport
{
[ForeignKey("Student")]
public int Id { get; set; }
public string RollNumber { get; set; }
public string StudentType { get; set; }
public Student Student { get; set; }
}
or, using the full set of Data Annotations from earlier:
public class Student
{
[Key]
public int Id { get; set; }
public string FullName { get; set; }
public StudentReport StudentReport { get; set; }
}
public class StudentReport
{
[Key, ForeignKey("Student")]
public int Id { get; set; }
public string RollNumber { get; set; }
public string StudentType { get; set; }
public Student Student { get; set; }
}
(source: mcainsh.info)
The tables are just for an example, what I am trying to do is map a virtual Manufacturer in the Book entity. I've tried using data annotation similar to below:
[ForeignKey("PublisherId")]
public virtual Publisher { get; set; }
[ForeignKey("Publisher.ManufacturerCompanyId")]
[InverseProperty("ManufacturerId")]
public virtual Manufacturer { get; set; }
Is this something that can be done?
You're configuring incorrectly the foreign keys. To do what you want, your model should be like this:
public class Book
{
public int Id { get; set; }
public string Title{ get; set; }
public int PublisherId { get; set; }
[ForeignKey("PublisherId")]
public virtual Publisher Publisher{ get; set; }
public int ManufacturerId { get; set; }
[ForeignKey("ManufacturerId")]
public virtual Manufacturer Manufacturer { get; set; }
}
public class Manufacturer
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Publisher
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Book> Books { get; set; }
}
In this model you have two one-to-many relationships, the first between Book and Publisher and the second one between Book and Manufacturer. As you can see in the Book class, if you want to use a FK property you must declare a property of the same type of the PK of the related entity (see PublisherId and ManufacturerId).Now, you can apply the ForeignKey annotation to the navigation property and tell it which property is the foreign key for the relationship, as I show above. Alternatively, you can addForeignKey attribute to the ManufacturerId, along with information telling it which navigation property represents the relationship it is a foreign key for:
[ForeignKey("Manufacturer")]
public int ManufacturerId { get; set; }
public virtual Manufacturer Manufacturer { get; set; }
If you want, you don't need to create the FKs properties, EF will do the job for you begin the escene. It will create a FK row in your Books table for each relationship (check the DB after execute your code):
public class Book
{
public int Id { get; set; }
public string Title{ get; set; }
//public int PublisherId { get; set; }
//[ForeignKey("PublisherId")]
public virtual Publisher Publisher{ get; set; }
//public int ManufacturerId { get; set; }
//[ForeignKey("ManufacturerId")]
public virtual Manufacturer Manufacturer { get; set; }
}
Below are my domain entities
public class User
{
public int Id { get; set; }
public string Firstname { get; set; }
public string Lastname { get; set; }
public DateTime? DateOfBirth { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public string EmailAddress { get; set; }
public RoleType RoleType { get; set; }
}
public class Role
{
public int Id { get; set; }
public string Name { get; set; }
}
I have made RoleType as a complex type (to acheive enum mapping). So I could use something like context.Users.FirstOrDefault(u => u.RoleType.Value == (long)RoleTypes.Admin)
RoleTypes.Admin is an enum mapping to the Role entity
public class RoleType
{
public int Value { get; set; }
// And all the implicit operators to map with enum
}
And then I have created a mapping using fluent api
public class RoleTypeMapping : ComplexTypeConfiguration<RoleType>
{
public RoleTypeMapping()
{
Property(r => r.Value)
.HasColumnName("RoleId"); // To make sure that in RoleType property of User EF entity maps to an int column [RoleId] in database (table [Users])
}
}
Using fluent-api, I want to create a foreign key association in [Users] table for [Users].[RoleId] referencing [Role].[Id]. Please can anyone provide me guidance to acheive this
I tired adding a property of type Role and creating a mapping through fluent-api, but EF creates another column Role_Id and makes it the foreign key. I want the existing [RoleId] column (complex type) to be the foreign key
It is not possible. If you want to have association with Role table you must abandon your enum-like approach and define Users entity like:
public class User
{
public int Id { get; set; }
public string Firstname { get; set; }
public string Lastname { get; set; }
public DateTime? DateOfBirth { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public string EmailAddress { get; set; }
public Role Role { get; set; }
}
First of all relations are not enums and complex types cannot contain navigation properties (as well as foreign keys).