Error upgrating to Entity Framework Core 3: RelationalReferenceCollectionBuilderExtensions does not exist in the current context - entity-framework

Im upgrating from Entity Framework Core 2 to Entity Framework Core 3. And I have this error:
Error CS0103 The name 'RelationalReferenceCollectionBuilderExtensions'
does not exist in the current context
The error is on method OnModelCreating(ModelBuilder modelBuilder), this is the code:
modelBuilder.Entity<Person>(entity =>
{
//some props
RelationalReferenceCollectionBuilderExtensions.HasConstraintName((ReferenceCollectionBuilder)entity
.HasOne(d => d.RuleCodeNavigation)
.WithMany(p => p.Person)
.HasForeignKey(d => d.RuleCode)
.OnDelete(DeleteBehavior.ClientSetNull), "FK_Person_Rules");
});
It seems the class RelationalReferenceCollectionBuilderExtensions does not exist in EF Core 3.
Any idea how I can fix this?

Not sure what happened to RelationalReferenceCollectionBuilderExtensions, but the suggested method to name your constraints is this
modelBuilder.Entity<Person>(entity =>
{
//some props
entity
.HasOne(d => d.RuleCodeNavigation)
.WithMany(p => p.Person)
.HasForeignKey(d => d.RuleCode)
.OnDelete(DeleteBehavior.ClientSetNull)
.HasConstraintName("FK_Person_Rules");
});

Related

Entity Framework Map() property alternate in EF Core 6

I am migrating my project from Entity Framework to EF Core 6 but now I am stuck at this point.
modelBuilder.Entity<tblStoreGroup>()
.HasMany(e => e.tblUsers)
.WithMany(e => e.tblStoreGroups)
.Map(m => m.ToTable("tblBridgeUserGroup")
.MapLeftKey("GroupID")
.MapRightKey("username"));
Because the Map() property is not available in EF Core, can someone please provide a solution for this code?
I am a beginner in Entity Framework.
Thanks in advance
You can try using UsingEntity:
modelBuilder.Entity<tblStoreGroup>()
.HasMany(p => p.tblUsers)
.WithMany(p => p.tblStoreGroups)
.UsingEntity<Dictionary<string, object>>(
"tblBridgeUserGroup",
j => j
.HasOne<tblUser>()
.WithMany()
.HasForeignKey("username"),
j => j
.HasOne<tblStoreGroup>()
.WithMany()
.HasForeignKey("GroupID"));
See Joining relationships configuration section of the docs.

How to Exclude from migration Auto-Generated table in EF?

i have table Asp_net_users which is many-to-many relation with table Clients. There are no mapped object in between them, it been auto -generated by EF:
modelBuilder.Entity<Client>(entity =>
{
entity.Property(e => e.State)
.HasConversion<string>();
entity.HasMany(d => d.Users)
.WithMany(p => p.Clients)
.UsingEntity<Dictionary<string, object>>(
"ClientUser",
l => l.HasOne<AspNetUser>().WithMany().HasForeignKey("UserId"),
r => r.HasOne<Client>().WithMany().HasForeignKey("ClientId"),
j =>
{
j.HasKey("ClientId", "UserId");
j.ToTable("client_users"); // ,"identity"
j.IndexerProperty<string>("ClientId");
j.IndexerProperty<string>("UserId");
});
});
The code above generating table client_users which i don't want in my migration.
I've tried to add to code above:
.Metadata
.SetIsTableExcludedFromMigrations(true)
no luck.
I know I can exclude using this method
modelBuilder.Entity<AspNetUser>().ToTable("asp_net_users", "identity", t => t.ExcludeFromMigrations());
but the problem is: above mentioned table is auto generated and I don't know how to do ToTable on it.
tried
modelBuilder.Entity().ToTable("client_users", t => t.ExcludeFromMigrations());
but it don't compile. modelBuilder.Entity() wants to have an object.
Please help
I added j.Metadata.SetIsTableExcludedFromMigrations(true); inside and it worked:
entity.HasMany(d => d.Users)
.WithMany(p => p.Clients)
...
j =>
{
...
j.Metadata.SetIsTableExcludedFromMigrations(true);
});

Load Related Data

I'm learning ASP.NET Core Web API and Entity Framework Core. Currently, I'm stuck figuring out how to populate the foreign keys with the actual values, as shown below.
Current Result:
Desired Result:
fkSecuritySecurityTypeId and fkSecurityExchangeId are populated.
DatabaseContext.cs:
The DatabaseContext class was built using dotnet ef dbcontext scaffold. Here's a portion of it:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Security>(entity =>
{
entity.HasOne(d => d.FkSecurityExchange)
.WithMany(p => p.Securities)
.HasForeignKey(d => d.FkSecurityExchangeId)
.OnDelete(DeleteBehavior.ClientSetNull);
entity.HasOne(d => d.FkSecuritySecurityType)
.WithMany(p => p.Securities)
.HasForeignKey(d => d.FkSecuritySecurityTypeId)
.OnDelete(DeleteBehavior.ClientSetNull);
});
Research:
AutoInclude() seems like the solution. I'm having a hard time understanding how to use AutoInclude() in my code since obviously my code is a bit different from how the docs use AutoInclude.
Questions:
Is AutoInclude() the correct approach ?
If so, how should it be used in this case ?
Thanks for your help.

Foreign key object is getting "instance is already tracked" error in unit tests

In the screenshot below, I'm trying to attach an Answer object so that it can be updated. However, this causes the error: "The instance of entity type 'QuestionSet' cannot be tracked because another instance with the key value '{QuestionSetId: 3}' is already being tracked."
The QuestionSet is indeed being tracked, so I don't think I'm confused about that part. However this error doesn't make sense to me, since I'm trying to update the Answer record, not the QuestionSet record. Shouldn't the contents of the QuestionSet field be irrelevant? I'm not trying to perform an operation that affects the related QuestionSet record, so why am I getting this error?
It's important to note that this error is ONLY happening when I run unit tests. The code works just fine outside of unit tests.
Here's the context setup code I'm using for my unit tests:
DbContextOptions<SurveyApplicationDbContext> options = new DbContextOptionsBuilder<Infrastructure.Data.EntityFramework.SurveyApplicationDbContext>()
.EnableSensitiveDataLogging()
.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking)
.UseInMemoryDatabase(databaseName: "SurveyApplicationDbContext" + dbNameSuffix).Options;
var context = new SurveyApplicationDbContext(options);
context.Survey.Add(new Survey
{
SurveyId = 123,
ClubId = "c1",
FormId = 1,
CreateDateUtc = DateTime.Now
});
context.Answer.Add(new Answer
{
SurveyId = 123,
QuestionSetId = 3,
AnswerValue = "Answer Value",
});
context.QuestionSet.Add(new QuestionSet
{
QuestionSetId = 3,
QuestionId = Constants.ScoreQuestionId,
SectionId = Constants.SummarySectionId,
FormId = 1
});
context.SaveChanges();
_mockSurveyUnitOfWork.Setup(x => x.SurveyRepository).Returns(new SurveyRepository(context));
_mockSurveyUnitOfWork.Setup(x => x.AnswerRepository).Returns(new AnswerRepository(context));
_mockSurveyUnitOfWork.Setup(x => x.QuestionSetRepository).Returns(new QuestionSetRepository(context));
}
And here is my DbContext model setup code for Answer:
modelBuilder.Entity<Answer>(entity =>
{
entity.ToTable("answer");
entity.HasIndex(e => new { e.QuestionSetId, e.SurveyId })
.HasName("UCanswer_questionSetId-surveyId")
.IsUnique();
entity.Property(e => e.AnswerId).HasColumnName("answerId");
entity.Property(e => e.AnswerValue)
.HasColumnName("answerValue")
.HasMaxLength(800)
.IsUnicode(false);
entity.Property(e => e.CreateDateUtc)
.HasColumnName("createDateUTC")
.HasColumnType("datetime");
entity.Property(e => e.ModifiedDateUtc)
.HasColumnName("modifiedDateUTC")
.HasColumnType("datetime");
entity.Property(e => e.QuestionSetId).HasColumnName("questionSetId");
entity.Property(e => e.ScoreValue)
.HasColumnName("scoreValue")
.HasColumnType("decimal(3, 2)");
entity.Property(e => e.SurveyId).HasColumnName("surveyId");
entity.HasOne(d => d.QuestionSet)
.WithMany(p => p.Answer)
.HasForeignKey(d => d.QuestionSetId)
.OnDelete(DeleteBehavior.ClientSetNull)
.HasConstraintName("FKanswer_questionSet_questionSetId");
entity.HasOne(d => d.Survey)
.WithMany(p => p.Answer)
.HasForeignKey(d => d.SurveyId)
.OnDelete(DeleteBehavior.ClientCascade)
.HasConstraintName("FKanswer_survey_surveyId");
});
Obviously there's more code involved that could be causing this error, but I didn't want to overload this post with too much code. Please let me know if I should provide more details. Mainly I want to understand this error on a conceptual level: why is it complaining about tracking QuestionSet even though I'm not trying to update it?

multiple tables mapping entity framework code first

I have 3 Entities Roles, Modules and Permissions and I am following code first approach using EF 6
Roles has RoleID , Modules has ModuleID and Permissions has PermissionID as Keys.
Now I want Map these 3 ID values to another mapping table RoleAccess on creating Role
I am able to map entity to with ICollection property and the same is not working for the above scenario.
help me out with code suggestions...
The configuration i am trying add is below..
'this is the mapping configuration i am trying `this.ToTable("Roles");
//this.HasKey(c => c.Id)
// .HasMany(c => c.Permissions)
// .WithRequired()
// .HasForeignKey(c => new { c.SubModuleId, c.EntitlementTypeId });
this.HasMany(a => new[] {a.SubModules,a.EntitlementTypes})
.WithMany(b => b.Roles)
.Map(mc =>
{
mc.ToTable("Permissions");
mc.MapLeftKey("RoleId");
mc.MapRightKey(new[] { "SubModuleId", "EntitlementTypeId" });
});`'