Here are Entities:
public class Entity
{
public int Id { get; set; }
public DateTime CreatedOn { get; set; }
public DateTime? ModifiedOn { get; set; }
}
public class EntityBase : Entity
{
[ForeignKey("CreatedBy")]
public int CreatedById { get; set; }
public User CreatedBy { get; set; }
[ForeignKey("ModifiedBy")]
public int? ModifiedById { get; set; }
public User ModifiedBy { get; set; }
}
public class ProjectRequest : EntityBase
{
public string RequestTitle { get; set; }
public string RequestType { get; set; }
...
public virtual ICollection<Material> Materials { get; set; }
public virtual ICollection<Translation> Translations { get; set; }
}
public class Material : EntityBase
{
[ForeignKey("ProjectRequest")]
public int ProjectRequestId { get; set; }
public virtual ProjectRequest ProjectRequest { get; set; }
...
public virtual ICollection<Translation> Translations { get; set; }
}
public class Translation:EntityBase
{
[ForeignKey("ProjectRequest")]
public int ProjectRequestId { get; set; }
public virtual ProjectRequest ProjectRequest { get; set; }
[ForeignKey("Material")]
public int MaterialId { get; set; }
public virtual Material Material { get; set; }
public string ProductMasterText { get; set; }
[MaxLength(40)]
public string ShortDescription { get; set; }
public string MasterDescriptionLine1 { get; set; }
public string MasterDescriptionLine2 { get; set; }
public string MasterDescriptionLine3 { get; set; }
public string LanguageCode { get; set; }
}
No modifications has been done to these entities using fluent API.
Now, whenever I try to insert object of type ProjectRequest with Materials and Translations nested in it, in Translation objects ProjectRequestId is set to 0.
Following is sample Change Tracker snapshot:
Can anyone help me on this? Why ProjectRequestId is 0 but MaterialId properly assigned in Transaltion objects?
I'm getting this error when trying to update relationship (one to one)
with fluent api this are my classes :
public class Organisation
{
[Key]
public int OrganisationId { get; set; }
public string organisationName { get; set; }
public string FirstName { get; internal set; }
public string LastName { get; internal set; }
public virtual ApplicationUser User { get; set; }
[Required]
public string ApplicationUserId { get; set; }
public int? OrganisationDetalisId { get; set; }
public virtual OrganisationDetalis OrDetalis { get; set; }
public virtual ICollection<Aeroa> aeroa { get; set; }
public virtual ICollection<Order> orders { get; set; }
}
public class OrganisationDetalis
{
[Key]
public int OrganisationDetalisId { get; set; }
//remove for clear code
public int OrganisationId { get; set; }
public virtual Organisation organisation { get; set; }
}
public DbSet<Organisation> organisation { get; set; }
public DbSet<OrganisationDetalis> OrDetalis { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<OrganisationDetalis>()
.HasKey(o => o.OrganisationId);
modelBuilder.Entity<Organisation>()
.HasOptional(ad => ad.OrDetalis).WithRequired(oo => oo.organisation);
}
but I keep getting that error when updating view nugget console
where is the problem?
I would like to create Resource and RelatedResources table with EF Code First as below:
Table Resource
int Id
string ResourceName
int Category
Table RelatedResource
int ResourceId
int RelatedResourceId
I tried as below but
Error: The ForeignKeyAttribute on property 'ResourceId' on type 'Models.ResourceRelated' is not valid. The navigation property 'Resource' was not found on the dependent type 'Models.ResourceRelated'. The Name value should be a valid navigation property name.
public class ResourceRelated
{
[ForeignKey("Resource")]
public int ResourceId { get; set; }
public virtual Resource Resoure { get; set; }
public virtual ICollection<Resource> RelatedResource { get; set; }
}
Kindly Advice!
If you want RelatedResource table, than you want many-to-many relationship. You can achieve this in next way
public class Resource
{
public int ResourceId { get; set; }
public string ResourceName { get; set; }
public int Category { get; set; }
[InverseProperty("Resoure")]
public virtual ICollection<RelatedResource> RelatedResource { get; set; }
[InverseProperty("ResourceRelated")]
public virtual ICollection<RelatedResource> ResourceRelated { get; set; }
}
public class RelatedResource
{
[Key]
[Column(Order = 1)]
[ForeignKey("Resoure")]
public int ResourceId { get; set; }
[Key]
[Column(Order = 2)]
[ForeignKey("ResourceRelated")]
public int ResourceRelatedId { get; set; }
public virtual Resource Resoure { get; set; }
public virtual Resource ResourceRelated { get; set; }
}
If you prefer do not work with RelatedResource in code, than you can do next
public class Resource
{
public int ResourceId { get; set; }
public string ResourceName { get; set; }
public int Category { get; set; }
public virtual ICollection<Resource> RelatedResource { get; set; }
public virtual ICollection<Resource> ResourceRelated { get; set; }
}
After you need next additional configuration
internal class ResourceConfiguration : EntityTypeConfiguration<Resource>
{
public ResourceConfiguration()
{
HasMany(s => s.ResourceRelated).WithMany(c => c.RelatedResource)
.Map(cs => {
cs.MapLeftKey("ResourceId");
cs.MapRightKey("RelatedResourceId");
cs.ToTable("RelatedResource"); }
);
}
}
And finally add this configuration
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
///other configuration code
modelBuilder.Configurations.Add(new ResourceConfiguration());
}
But if you want to have "resource tree" than you do not need RelatedResource table
public class Resource
{
public int ResourceId { get; set; }
public string ResourceName { get; set; }
public int Category { get; set; }
public int? ResourceRelatedId { get; set; }
public Resource ResourceRelated { get; set; }
[ForeignKey("ResourceRelatedId")]
public virtual ICollection<Resource> RelatedResource { get; set; }
}
I have the following 2 entities:
public class Team
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Fixture> Fixtures { get; set; }
}
public class Fixture
{
public int Id { get; set; }
public Result Result { get; set; }
public int HomeTeamId { get; set; }
public int AwayTeamId { get; set; }
public virtual Team HomeTeam { get; set; }
public virtual Team AwayTeam { get; set; }
}
I have then mapped it like so:
public class FixtureMap : EntityTypeConfiguration<Fixture>
{
public FixtureMap()
{
HasRequired(x => x.AwayTeam).WithMany().HasForeignKey(x => x.AwayTeamId);
HasRequired(x => x.HomeTeam).WithMany().HasForeignKey(x => x.HomeTeamId);
}
}
But when I add a migration, EF is creating an additional FK and column to my Fixture table and I've no idea why? How can I tell it not too?
As you can see its added a column called Team_Id and created an FK from it even tho I have specified the relationship in the mapping?
use this code:
public class Team
{
public int Id { get; set; }
public string Name { get; set; }
[InverseProperty("HomeTeam")]
public virtual ICollection<Fixture> HomeFixtures { get; set; }
[InverseProperty("AwayTeam")]
public virtual ICollection<Fixture> AwayFixtures { get; set; }
}
public class Fixture
{
public int Id { get; set; }
public Result Result { get; set; }
public int HomeTeamId { get; set; }
public int AwayTeamId { get; set; }
[InverseProperty("HomeFixtures")]
[ForeignKey("HomeTeamId ")]
public virtual Team HomeTeam { get; set; }
[InverseProperty("AwayFixtures")]
[ForeignKey("AwayTeamId")]
public virtual Team AwayTeam { get; set; }
}
And :
public class FixtureMap : EntityTypeConfiguration<Fixture>
{
public FixtureMap()
{
HasRequired(x => x.AwayTeam).WithMany().HasForeignKey(x => x.AwayTeamId).willCascadeOnDelete(false);
HasRequired(x => x.HomeTeam).WithMany().HasForeignKey(x => x.HomeTeamId);
}
}
I am learning EF Code First with migrations, I have 3 entities :
[User] 1--->* [Call] 1--->* [ETA]
Code :
User.cs
public class User
{
[Key]
public int Id { get; set; }
public Guid LongId { get; set; }
[Required]
public string Name { get; set; }
public virtual ICollection<Call> Calls { get; set; } // many calls
public User()
{
LongId = Guid.NewGuid();
}
}
Call.cs
public class Call
{
[Key]
public int Id { get; set; }
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public string BreakdownNo { get; private set; }
[Required,MaxLength(32)]
public string Customer { get; set; }
[Required,MaxLength(32)]
public string TrailerNo { get; set; }
[Required, MaxLength(32)]
public string DepotContact { get; set; }
[Required, MaxLength(48), RegularExpression(#"^[_a-z0-9-]+(\.[_a-z0-9-]+)*#[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,4})$")]
public string DepotEmail { get; set; }
[Required, MinLength(9), MaxLength(32)]
public string DepotPhone { get; set; }
[Required, MaxLength(32)]
public string DriverContact { get; set; }
[Required, MinLength(9), MaxLength(32), RegularExpression(#"^(7\d{3}|\(?07\d{3}\)?)\s?\d{3}\s?\d{3}$")]
public string DriverPhone { get; set; }
[Required, MaxLength(256)]
public string LocatedAtFreeText { get; set; }
[Required, MaxLength(8), RegularExpression(#"^([A-PR-UWYZ0-9][A-HK-Y0-9][AEHMNPRTVXY0-9]?[ABEHMNPRVWXY0-9]? {0,1}[0-9][ABD-HJLN-UW-Z]{2}|GIR 0AA)$")]
public string LocatedAtPostCode { get; set; }
[Required, MaxLength(16)]
public string StartupNo { get; set; }
[Required]
public bool IsLoaded { get; set; }
[Required, MaxLength(256)]
public string FaultDescription { get; set; }
[Required]
public DateTime StartTime { get; set; }
public DateTime? EndTime { get; set; }
public string Status { get; set; }
public virtual User Controller { get; set; } // 1 controller
public virtual ICollection<ETA> ETAs { get; set; } // many ETAs
public Call()
{
StartTime = DateTime.Now;
ETAs = new List<ETA> { new ETA() };
Status = "Logged";
}
}
ETA.c
public class ETA
{
[Key]
public int Id { get; set; }
[Required]
public TimeSpan Value { get; set; }
public int CallId { get; set; }
public ETA()
{
Value = TimeSpan.FromMinutes(90);
}
}
I would like it so when I delete the User it deletes all of the Calls for the User, which in turn deletes all of the ETAs for those Calls.
When I delete a User row from the Database (using database explorer) it gives me an error :
No rows were deleted.
A problem occurred attempting to delete row 201.
Error Source: .Net SqlClient Data Provider.
Error Message: The DELETE statement conflicted with the REFERENCE constraint "FK_dbo.Calls_dbo.Users_Controller_Id". The conflict occurred in database "BreakdownDb", table "dbo.Calls", column 'Controller_Id'.
You can turn on the Cascade Delete option in Entity Framework, here you will find more info:
http://blogs.msdn.com/b/alexj/archive/2009/08/19/tip-33-how-cascade-delete-really-works-in-ef.aspx
The solution was to add OnModelCreating method to my DbContext class :
public class BreakdownDb : DbContext
{
public DbSet<Call> Calls { get; set; }
public DbSet<User> Users { get; set; }
public BreakdownDb(): base("name=DefaultConnection") {}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<User>().HasMany(x => x.Calls).WithRequired();
modelBuilder.Entity<Call>().HasMany(x => x.ETAs).WithRequired();
}
}