Hi! I have some relational issues between two tables, one - to - many.
The whole concept is as follows:
Table 1: Country:
Besides it's own fields it also contains two ICollections where one points to a collection of regions and the other on cities.
Table 2: Region
Besides it's own fields, it also contains a CountryId and a ICollection of Cities.
Table 3: City
Besides it's own fields, it also contains a CountryId and a RegionId (where regionId can be nullable).
The principal idea is that a Country can have region(s) or/and city(ies).
This means that each foreign key from region/city to the CountryId cannot be null. But, the foreign key from City To Region is allowed to be null, since "some" Countries, in this case, regions is unnecessary.
Observe that all three tables is also refering, with an ICollection, to a middle table wich in turn stores the relation between them.
Country Entity:
public class Country
{
public Guid Id { get; set; }
public int CountryId { get; set; }
public Guid ComponentId { get; set; }
public string NumCode { get; set; }
public string Code2 { get; set; }
public string Code3 { get; set; }
public virtual ICollection<Region> Regions { get; set; }
public virtual ICollection<City> Cities { get; set; }
public virtual ICollection<AdvertGeography> AdvertsGeographies { get; set; }
}
public class CountryMap()
{
// Primary Key
HasKey(t => t.Id);
Property(e => e.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
// Unique Index
Property(e => e.ComponentId)
.HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute("IX_Unique_Component", 1) { IsUnique = true }));
Property(e => e.CountryId)
.HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute("IX_Unique_Country", 1) { IsUnique = true }));
// Properties
// Table & Column Mappings
ToTable("Country");
Property(e => e.Id).HasColumnName("Id");
Property(e => e.CountryId).HasColumnName("CountryId");
Property(e => e.ComponentId).HasColumnName("ComponentId");
Property(e => e.Code2).HasColumnName("Code2");
Property(e => e.Code3).HasColumnName("Code3");
Property(e => e.NumCode).HasColumnName("NumCode");
// Relationships
HasMany(t => t.Regions)
.WithRequired(t => t.Country).WillCascadeOnDelete(false);
HasMany(t => t.Cities)
.WithRequired(t => t.Country).WillCascadeOnDelete(false);
}
Region Entity:
public class Region
{
public Region()
{
this.Cities = new HashSet<City>();
}
public Guid Id { get; set; }
public Guid CountryId { get; set; }
public virtual Country Country { get; set; }
public string Name { get; set; }
public virtual ICollection<Office> Offices { get; set; }
public virtual ICollection<City> Cities { get; set; }
public virtual ICollection<OpenApplication> OpenApplications { get; set; }
public virtual ICollection<Subscription> Subscriptions { get; set; }
public virtual ICollection<AdvertGeography> AdvertsGeographies { get; set; }
}
public class RegionMap()
{
// Primary Key
HasKey(t => t.Id);
Property(e => e.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
// Unique Index
Property(e => e.Name)
.HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute("IX_Unique", 1) { IsUnique = true }));
Property(e => e.CountryId)
.HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute("IX_Unique", 2) { IsUnique = true }));
// Properties
Property(e => e.Name).IsRequired().HasMaxLength(512);
// Table & Column Mappings
ToTable("Region");
Property(e => e.Id).HasColumnName("Id");
Property(e => e.Name).HasColumnName("Name");
Property(e => e.CountryId).HasColumnName("CountryId");
// Relationships
HasMany(t => t.Subscriptions)
.WithMany(t => t.Regions);
HasMany(t => t.OpenApplications)
.WithMany(t => t.Regions);
HasMany(t => t.Offices)
.WithRequired(t => t.Region);
HasMany(t => t.Cities)
.WithRequired(t => t.Region);
HasRequired(t => t.Country).WithMany(t => t.Regions).WillCascadeOnDelete(false);
}
City Entity:
public class City
{
public Guid Id { get; set; }
public Guid CountryId { get; set; }
public virtual Country Country { get; set; }
public Guid? RegionId { get; set; }
public virtual Region Region { get; set; }
public string Name { get; set; }
public virtual ICollection<AdvertGeography> AdvertsGeographies { get; set; }
}
public class CityMap()
{
//Primary Key
HasKey(e => e.Id);
Property(e => e.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
//Unique Index
Property(e => e.Name)
.HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute("IX_Unique", 1) { IsUnique = true }));
//Properties
Property(e => e.Name).IsRequired().HasMaxLength(512);
//Table & Column Mappings
ToTable("City");
Property(e => e.Id).HasColumnName("Id");
Property(e => e.Name).HasColumnName("Name");
Property(e => e.CountryId).HasColumnName("CountryId");
Property(e => e.RegionId).HasColumnName("RegionId");
// Relationships
HasRequired(t => t.Country).WithMany(t => t.Cities).WillCascadeOnDelete(false);
HasOptional(t => t.Region).WithMany(t => t.Cities).HasForeignKey(t => t.RegionId);
}
/J
Anybody have an idea? Glad for any help
Best regards
Actually I have solved it now. I missied this in RegionMap:
Quite trivial, but when you stare too long at your code, these things easily slips through.
HasMany(t => t.Cities)
.WithRequired(t => t.Region);
Should be
HasMany(t => t.Cities)
.WithOptional(t => t.Region);
Thanks anyway.
/J
Related
I have complicated relationships between these entities:
Country
Airport
Airline
Flight
Country has many Airlines and many Airports.
Airline has one Countries, the same about Airport.
Airline has many Flights,
Airport has many DepartureFlights and ArrivalFlights (both are Flight type).
Flight has one Airline and one DepartureAirport and one ArrivalAirport (both are Airport type).
Country can have no airlines and airports,
Airline can have no Flights,
Airport can have neither DepartureFlights nor ArrivalFlights.
What I am trying to do is when Country is deleted, then all related Airlines and Airports are deleted, also when Airline or DepartureAirport or ArrivalAirport are deleted, all related Flights are deleted also,
but when updating my db after the migration is created I'm getting an error:
Introducing FOREIGN KEY constraint "FK_Flights_Airports_DepartureAirport" on table "Flights" may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
How to implement this behavior and prevent an error?
Here are my models:
Country:
public class Country
{
public int Id { get; set; }
/* other properties */
public virtual ICollection<Airport>? Airports { get; set; }
public virtual ICollection<Airline>? Airlines { get; set; }
}
Airline:
public class Airline
{
public int Id { get; set; }
/* other properties */
public int CountryId { get; set; }
public virtual Country Country { get; set; }
public virtual ICollection<Flight>? Flights { get; set; }
}
Airport:
public class Airport
{
public int Id { get; set; }
public string Name { get; set; }
/* other properties */
public int CountryId { get; set; }
public virtual Country Country { get; set; }
public virtual ICollection<Flight>? DepartureFlights { get; set; }
public virtual ICollection<Flight>? ArrivalFlights { get; set; }
}
Flight:
public class Flight
{
public int Id { get; set; }
/* other properties */
public int AirlineId { get; set; }
public int DepartureAirportId { get; set; }
public int ArrivalAirportId { get; set; }
public virtual Airline Airline { get; set; }
public virtual Airport DepartureAirport { get; set; }
public virtual Airport ArrivalAirport { get; set; }
}
After all the DBContext file:
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }
public DbSet<Airline> Airlines { get; set; }
public DbSet<Airport> Airports { get; set; }
public DbSet<Country> Countries { get; set; }
public DbSet<Flight> Flights { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Airline>(x =>
{
x.HasKey(a => a.Id);
x.HasOne(c => c.Country)
.WithMany(a => a.Airlines)
.HasForeignKey(a => a.CountryId)
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity<Airport>(x =>
{
x.HasKey(a => a.Id);
x.HasOne(c => c.Country)
.WithMany(a => a.Airports)
.HasForeignKey(a => a.CountryId)
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity<Country>(x =>
{
x.HasKey(c => c.Id);
});
modelBuilder.Entity<Flight>(x =>
{
x.HasKey(f => f.Id);
x.HasOne(a => a.Airline)
.WithMany(f => f.Flights)
.HasForeignKey(f => f.AirlineId)
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
x.HasOne(a => a.DepartureAirport)
.WithMany(f => f.DepartureFlights)
.HasForeignKey(f => f.DepartureAirportId)
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
x.HasOne(a => a.ArrivalAirport)
.WithMany(f => f.ArrivalFlights)
.HasForeignKey(f => f.ArrivalAirportId)
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
}
}
How to implement this behavior and prevent an error?
This is officially known issue. Therefore, We have two ways to handle this scenario thus the error:
1. Change one or more of the relationships to not cascade delete.
In this scenario, we could make the Country relationship with Airport, Flight and Airlines optional by giving it a nullable foreign key property: for instance we can do something like:
.IsRequired(false);
Note: You can check our official document for more details.
2. Configure the database without one or more of these cascade deletes,
then ensure all dependent entities are loaded so that EF Core can
perform the cascading behavior.
Considering this appreach we can keep the Airport, Flight and Airlines relationship required and configured for cascade delete, but make this configuration only apply to tracked entities, not the database: So we can do somethng like below:
modelBuilder.Entity<Airline>(x =>
{
x.HasKey(a => a.Id);
x.HasOne(c => c.Country)
.WithMany(a => a.Airlines)
.HasForeignKey(a => a.CountryId)
.OnDelete(DeleteBehavior.ClientCascade);
.IsRequired(false);
});
modelBuilder.Entity<Airport>(x =>
{
x.HasKey(a => a.Id);
x.HasOne(c => c.Country)
.WithMany(a => a.Airports)
.HasForeignKey(a => a.CountryId)
.OnDelete(DeleteBehavior.ClientCascade);
.IsRequired(false);
});
Note: You can apply same for Flight as well. In addition, As you may know OnDelete(DeleteBehavior.ClientCascade); or ClientCascade allows the DBContext to delete entities even if there is a cyclic ref or LOCK on it. Please read the official guideline for more details here
add these lines in "OnModelCreating"
var cascades = modelBuilder.Model.GetEntityTypes()
.SelectMany(t => t.GetForeignKeys())
.Where(fk => !fk.IsOwnership && fk.DeleteBehavior == DeleteBehavior.Cascade);
foreach (var fk in cascades)
fk.DeleteBehavior = DeleteBehavior.Restrict;
I have an ApplicationUser model:
public class ApplicationUser : IdentityUser
{
[Required]
public string FirstName { get; set; }
[Required]
public string LastName { get; set; }
public List<Project> Projects { get; set; }
}
... and a Project model:
public class Project
{
public int Id { get; set; }
public int? ParentProjectId { get; set; }
[Required]
public string ProjectCreatorId { get; set; }
[Required]
public string ProjectOwnerId { get; set; }
public string Title { get; set; }
public DateTime Created { get; set; }
public ApplicationUser ProjectCreator { get; set; }
public ApplicationUser ProjectOwner { get; set; }
public Project ParentProject { get; set; }
public virtual List<Project> ChildProjects { get; set; }
}
In OnModelCreating(), I tried this:
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Project>()
.HasMany(c => c.ChildProjects)
.WithOne(p => p.ParentProject)
.HasForeignKey(p => p.ParentProjectId);
modelBuilder.Entity<ApplicationUser>()
.HasMany(p => p.Projects)
.WithOne(o => o.ProjectOwner)
.HasForeignKey(po => po.ProjectOwnerId);
modelBuilder.Entity<ApplicationUser>()
.HasMany(p => p.Projects)
.WithOne(c => c.ProjectCreator)
.HasForeignKey(pc => pc.ProjectCreatorId);
But upon creating the database, I get
Cannot create a relationship between 'ApplicationUser.Projects' and 'Project.ProjectCreator', because there already is a relationship between 'ApplicationUser.Projects' and 'Project.ProjectOwner'. Navigation properties can only participate in a single relationship.
I tried the solutions to this old question, but wasn't able to make any of them work.
Is there another way I could keep track of both a Project's creator AND owner, and be able to .Include() them both in the queries?
Instead of different binding, use the single binding
modelBuilder.Entity<ApplicationUser>()
.HasMany(p => p.Projects)
.WithOne(o => o.ProjectOwner)
.HasForeignKey(po => po.ProjectOwnerId);
.WithOne(c => c.ProjectCreator)
.HasForeignKey(pc => pc.ProjectCreatorId);
I went for this solution:
As mentioned in the comments, ApplicationUser would need two List<Project>-properties:
public List<Project> CreatedProjects { get; set; }
public List<Project> OwnedProjects { get; set; }
Then, in OnModelCreating():
modelBuilder.Entity<Project>()
.HasOne(g => g.ProjectCreator)
.WithMany(t => t.CreatedProjects)
.HasForeignKey(t => t.ProjectCreatorId)
.HasPrincipalKey(t => t.Id);
modelBuilder.Entity<Project>()
.HasOne(g => g.ProjectOwner)
.WithMany(t => t.OwnedProjects)
.HasForeignKey(t => t.ProjectOwnerId).OnDelete(DeleteBehavior.NoAction)
.HasPrincipalKey(t => t.Id);
Now I'm able to include both creators and owners. :)
I have 3 entities mapped to each other with one-to-many relationship, one of them should be mapped to both of them which is resulting in unwanted many-to-many relationship.
Here is the logic behind the mapping:
User can have many Posts; Post has only one user.
User can have many Categories; Category has only one user.
Category can have many posts; Post has only one category.
Here is my code:
User
Table("Users")]
Public Class User
{
[Key]
public int UserId { get; set; }
[Required]
public string FirstName { get; set; }
[Required]
public string LastName { get; set; }
[Required]
public string UserName { get; set; }
public DateTime CreatedAt { get; set; }
public ICollection<Posts> Posts { get; set; }
public ICollection<Category> Categories { get; set; }
}
Post
[Table("Posts")]
public class Post
{
[Key]
public int PostId { get; set; }
[Required]
public string Title { get; set; }
[Required]
public string Description { get; set; }
[Required]
public string Text { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime? UpdatedAt { get; set; }
public int UserId { get; set; }
public User User { get; set; }
public int CategoryId { get; set; }
public Category Category { get; set; }
}
Category
[Table("Categories")]
public class Category
{
[Key]
public int CategoryId { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Description { get; set; }
public DateTime CreatedAt { get; set; }
public int UserId { get; set; }
public User User { get; set; }
public ICollection<Post> Posts { get; set; }
}
My Db Context
public class BlogContext : DbContext
{
public DbSet<User> Users { get; set; }
public DbSet<Post> Posts{ get; set; }
public DbSet<Category> Categories { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<User>(entity =>
{
entity.HasMany<Post>(s => s.Posts)
.WithOne(u => u.User)
.HasForeignKey(s => s.UserId)
.OnDelete(DeleteBehavior.Restrict);
entity.HasMany<Category>(c => c.Categories)
.WithOne(u => u.User)
.HasForeignKey(c => c.UserId)
.OnDelete(DeleteBehavior.Restrict);
entity.Property(u => u.CreatedAt)
.HasDefaultValueSql("SYSUTCDATETIME()");
});
modelBuilder.Entity<Post>(entity =>
{
entity.HasOne<Category>(s => s.Category)
.WithMany(c => c.Posts)
.HasForeignKey(s => s.PostId);
entity.HasOne<User>(s => s.User)
.WithMany(u => u.Posts)
.HasForeignKey(s => s.PostId);
entity.Property(s => s.CreatedAt)
.HasDefaultValueSql("SYSUTCDATETIME()");
});
modelBuilder.Entity<Category>(entity =>
{
entity.HasMany<Post>(c => c.Posts)
.WithOne(s => s.Category)
.HasForeignKey(c => c.PostId)
.OnDelete(DeleteBehavior.Restrict);
entity.Property(c => c.CreatedAt)
.HasDefaultValueSql("SYSUTCDATETIME()");
});
}
}
I ran into this problem when inserting posts:
The property 'PostId' on entity type 'Post' has a temporary value
What I understood is that I caused many-to-many relationship with the way that I've implemented the DbContext. How can I fix it? Thanks for helping.
You didn't configure the foreign key correctly. Let's review your code of Entity<Post>(entity=>{ /* ... */ }):
modelBuilder.Entity<Post>(entity =>
{
entity.HasOne<Category>(s => s.Category)
.WithMany(c => c.Posts)
.HasForeignKey(s => s.PostId); // line A: it is not correct!
entity.HasOne<User>(s => s.User)
.WithMany(u => u.Posts)
.HasForeignKey(s => s.PostId); // line B: it is not correct!
entity.Property(s => s.CreatedAt)
.HasDefaultValueSql("SYSUTCDATETIME()");
});
Note the line A and line B are not correct. As in both cases, the dependent entity is Post. Your code will result in a foreign key as below:
CREATE TABLE [Posts] (
[PostId] int NOT NULL,
[Title] nvarchar(max) NOT NULL,
[Description] nvarchar(max) NOT NULL,
[Text] nvarchar(max) NOT NULL,
[CreatedAt] datetime2 NOT NULL DEFAULT (SYSUTCDATETIME()),
[UpdatedAt] datetime2 NULL,
[UserId] int NOT NULL,
[CategoryId] int NOT NULL,
CONSTRAINT [PK_Posts] PRIMARY KEY ([PostId]),
CONSTRAINT [FK_Posts_Categories_PostId] FOREIGN KEY ([PostId]) REFERENCES [Categories] ([CategoryId]) ON DELETE NO ACTION,
CONSTRAINT [FK_Posts_Users_PostId] FOREIGN KEY ([PostId]) REFERENCES [Users] ([UserId]) ON DELETE NO ACTION
);
So you need change your code as below:
modelBuilder.Entity<Post>(entity =>
{
entity.HasOne<Category>(s => s.Category)
.WithMany(c => c.Posts)
//.HasForeignKey(s => s.PostId);
.HasForeignKey(s => s.CategoryId);
entity.HasOne<User>(s => s.User)
.WithMany(u => u.Posts)
//.HasForeignKey(s => s.PostId);
.HasForeignKey(s => s.UserId);
entity.Property(s => s.CreatedAt)
.HasDefaultValueSql("SYSUTCDATETIME()");
});
Because of the same reason, you should also change the part of Entity<Category>(entity=>{ /* ... */ }) as below:
modelBuilder.Entity<Category>(entity =>
{
entity.HasMany<Post>(c => c.Posts)
.WithOne(s => s.Category)
//.HasForeignKey(c => c.PostId) // remove this line
.HasForeignKey(c => c.CategoryId) // add this line
.OnDelete(DeleteBehavior.Restrict);
entity.Property(c => c.CreatedAt)
.HasDefaultValueSql("SYSUTCDATETIME()");
});
You made a mistake in
modelBuilder.Entity<Post>(entity =>
{
entity.HasOne<Category>(s => s.Category)
.WithMany(c => c.Posts)
.HasForeignKey(s => s.PostId);
entity.HasOne<User>(s => s.User)
.WithMany(u => u.Posts)
.HasForeignKey(s => s.PostId);
entity.Property(s => s.CreatedAt)
.HasDefaultValueSql("SYSUTCDATETIME()");
});
Table category model has not PostId, and User model has not too. Correct this.
I am using C# EF code-first. I have the following 2 classes:
public class Om_Currency
{
[Key]
public Int16 CurrencyID { get; set; }
public String CurrencySymbol { get; set; }
public Boolean IsActive { get; set; }
public Int32 CountryID { get; set; }
public virtual Om_Country Country { get; set; }
}
public class Om_Country
{
[Key]
public Int16 CountryID { get; set; }
public String CountryName { get; set; }
public Boolean IsActive { get; set; }
public Int32 CurrencyID { get; set; }
public virtual Om_Currency Currency { get; set; }
}
Now, I am trying to implement an 1-1 relationship between these 2 classes. So that I can get Currency details from Country and Country details can be fetched from Currency.
modelBuilder
.Entity<Om_Country>()
.HasOptional(f => f.Currency)
.WithRequired(s => s.Country);
modelBuilder
.Entity<Om_Currency>()
.HasOptional(f => f.Country)
.WithRequired(s => s.Currency);
But I get this error:
The navigation property 'Country' declared on type
'ObjectModel.Country.Om_Currency' has been configured with conflicting
multiplicities.
Am I doing something wrong?
This is the mapping class for Country:
public class CountryMap : EntityTypeConfiguration<Om_Country>
{
public CountryMap()
{
Property(x => x.CountryID)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
Property(x => x.CountryName)
.IsRequired()
.HasMaxLength(100)
.HasColumnAnnotation
(
IndexAnnotation.AnnotationName,
new IndexAnnotation
(
new IndexAttribute("U_CountryName", 1) { IsUnique = true }
)
);
Property(x => x.IsActive).IsRequired();
Property(x => x.CurrencyID).IsRequired();
ToTable(clsCommon.tblCountry);
}
}
and this is the mapping class for Currency:
public class CurrencyMap : EntityTypeConfiguration<Om_Currency>
{
public CurrencyMap()
{
Property(x => x.CurrencyID)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
Property(x => x.CurrencySymbol)
.IsRequired()
.IsVariableLength()
.HasMaxLength(50)
.HasColumnAnnotation
(
IndexAnnotation.AnnotationName,
new IndexAnnotation
(
new IndexAttribute("U_CurrencySymbol", 1) { IsUnique = true }
)
);
Property(x => x.IsActive).IsRequired();
Property(x => x.CountryID).IsRequired();
ToTable(clsCommon.tblCurrency);
}
}
I figured out the issue. I got the Solution from here
Instead of below
modelBuilder
.Entity<Om_Country>()
.HasOptional(f => f.Currency)
.WithRequired(s => s.Country);
modelBuilder
.Entity<Om_Currency>()
.HasOptional(f => f.Country)
.WithRequired(s => s.Currency);
It should be below
modelBuilder.Entity<Om_Country>()
.HasRequired(x => x.Currency).WithMany()
.HasForeignKey(x => x.CurrencyID).WillCascadeOnDelete(false);
modelBuilder.Entity<Om_Currency>()
.HasRequired(x => x.Country).WithMany()
.HasForeignKey(x => x.CountryID).WillCascadeOnDelete(false);
I am having some trouble with EF6 lazy loading, code first to an existing database.
Here are the Entities that are giving me the issue, I have no idea why it is not working, everything I find online says it should be working.
public class User
{
public long UserId { get; set; }
public string Email { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public virtual ICollection<Token> Tokens { get; set; }
public virtual ICollection<Business> Businesses { get; set; }
public virtual ICollection<Candidate> Candidates { get; set; }
}
Here is the configuration mappings:
public class Token
{
public long TokenId { get; set; }
public long UserId { get; set; }
public Guid TokenValue { get; set; }
public DateTime ExpirationDate { get; set; }
public virtual User User { get; set; }
}
public TokenMap()
{
this.HasKey(t => t.TokenId);
this.Property(t => t.TokenValue)
.IsRequired();
this.Property(t => t.ExpirationDate)
.IsRequired();
this.ToTable("Tokens");
this.Property(t => t.TokenId).HasColumnName("TokenId");
this.Property(t => t.UserId).HasColumnName("UserId");
this.Property(t => t.TokenValue).HasColumnName("TokenValue");
this.Property(t => t.ExpirationDate).HasColumnName("ExpirationDate");
this.HasRequired(s => s.User)
.WithMany(s=>s.Tokens)
.HasForeignKey(s=>s.UserId);
}
public UserMap()
{
this.ToTable("Users");
this.HasKey(t => t.UserId);
this.Property(t => t.Email)
.IsRequired();
this.Property(t => t.FirstName)
.IsRequired();
this.Property(t => t.LastName)
.IsRequired();
this.HasMany(t => t.Businesses)
.WithMany(set => set.Users)
.Map(m =>
{
m.ToTable("BusinessUser");
m.MapLeftKey("UserId");
m.MapRightKey("BusinessId");
});
this.HasMany(s => s.Tokens)
.WithRequired(s => s.User)
.HasForeignKey(s => s.UserId);
this.HasMany(s => s.Candidates)
.WithOptional(s => s.User)
.HasForeignKey(s => s.UserId);
}
And here is a few snippets from the context:
public DbSet<Token> Token { get; set; }
public DbSet<User> User { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new TokenMap());
modelBuilder.Configurations.Add(new UserMap());
}
Whenever I do a SingleOrDefault on the Tokens entity the result' user is null.
Any idea what I am doing wrong? All the data in the database is right, and UserId does have a value.
Here is a more elaborate example of calling:
I am implementing the repository patern.
In the class doing the call' constructor I have:
context = new Consolid8ContextProvider();
uow = new UnitOfWork(context);
And then uow.Tokens.First(u => u.ExpirationDate > DateTime.Now && u.TokenValue == token);
Tokens is my TokenRepository that exposes the Tokens entity, and First is a wrapper for FirstOrDefault.
This results in a token object with all of the properties set except for the User navigation property
So I was using BreezeJS and it overrides your context with it's own settings, part of which is to set LazyLoading and EnableProxiesCreation to false.
So if you want to do queries outside of breeze you either have to implement a different constructor for your breeze provider or setting it per query as Slauma has suggested in the comments of the question.