EF Core group by problem, duplicated rows - c#

The problem is that when the method runs, it creates rows for the CariHareket table, no matter how many rows of the tables linked to the Kontrat.
I can't group by because EF Core doesn't support it (EF Core v3.1.9)
hareketService.GetAll(Predicate())//table name is CariHareket
.Include(s => s.Cari)
.Include(s => s.HedefHareketCariVirman)
.Include(s => s.HareketCari)
.Include(s => s.Kontrat).ThenInclude(s => s.KontratKalemler)
.Include(s => s.Kontrat).ThenInclude(s => s.KontratTarihBaglantilar)
.Include(s => s.Kontrat).ThenInclude(s => s.FaturaTalimativeTurkceFatura)
.Include(s => s.Kontrat).ThenInclude(s => s.AraciCari)
CariHareket and Kontrat model classes:
public class CariHareket
{
[Key]
public int ID { get; set; }
[ForeignKey(nameof(CariID))]
public virtual Cariler Cari { get; set; }
public int? CariID { get; set; }
[ForeignKey(nameof(KontratID))]
public virtual KontratUst Kontrat { get; set; }
public int? KontratID { get; set; }
[ForeignKey(nameof(HareketCariID))]
public virtual Cariler HareketCari { get; set; }
public int? HareketCariID { get; set; }
[ForeignKey(nameof(HedefHareketCariVirmanID))]
public virtual Cariler HedefHareketCariVirman { get; set; }
public int? HedefHareketCariVirmanID { get; set; }
...
}
public class Kontrat
{
...
[InverseProperty("Kontrat")]
public virtual BindingList<KontratMasraflarNotlar> KontratMasraflarNotlar { get; set; }
[InverseProperty("Kontrat")]
public virtual BindingList<KontratKalem> KontratKalemler { get; set; }
[InverseProperty("Kontrat")]
public virtual BindingList<KontratTarihBaglantilar> KontratTarihBaglantilar { get; set; }
[InverseProperty("Kontrat")]
public virtual BindingList<KontratKasa> KontratKasa { get; set; }
[InverseProperty("Kontrat")]
public virtual BindingList<KontratKonteyner> KontratKonteyner { get; set; }
[InverseProperty("Kontrat")]
public virtual BindingList<KontratTurkceFaturaKalem> FaturaTalimativeTurkceFatura { get; set; }
}

Related

EF7 all related entities in ICollection loaded twice

I have two entities, Function and Department with a Many to Many table in between.
public class Department
{
public Department()
{
DepartmentFunctions = new HashSet<DepartmentFunction>();
PersonFunctions = new HashSet<PersonFunction>();
}
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<DepartmentFunction> DepartmentFunctions { get; set; }
public DateTime? DeletedAt { get; set; }
}
public class Function
{
public Function()
{
DepartmentFunctions = new HashSet<DepartmentFunction>();
FunctionTaskProfiles = new HashSet<FunctionTaskProfile>();
PersonFunctions = new HashSet<PersonFunction>();
}
public int Id { get; set; }
public string Name { get; set; }
public float? ItemOrder { get; set; }
public virtual Organisation Organisation { get; set; }
public virtual ICollection<DepartmentFunction> DepartmentFunctions { get; set; }
public virtual ICollection<FunctionTaskProfile> FunctionTaskProfiles { get; set; }
public virtual ICollection<PersonFunction> PersonFunctions { get; set; }
public DateTime? DeletedAt { get; set; }
}
public class DepartmentFunction
{
public int FunctionId { set; get; }
public int DepartmentId { get; set; }
public virtual Department Department { get; set; }
public virtual Function Function { get; set; }
}
When the departmentfunction on either entity is loaded, either with eager loading or lazy loading, every unique DepartmentFunction is listed twice. This problem occured after updating from EF core 5 to EF core 7. I have not changed anything with that update.
I have tried explicitly configuring the relation like this:
modelBuilder.Entity<DepartmentFunction>(entity =>
{
entity.HasKey(e => new {FunctieId = e.FunctionId, AfdelingId = e.DepartmentId})
.HasName("PK__Afdeling__591131EC594F97A1");
entity.HasOne(d => d.Department)
.WithMany(p => p.DepartmentFunctions)
.HasForeignKey(d => d.DepartmentId)
.OnDelete(DeleteBehavior.ClientSetNull);
entity.HasOne(d => d.Function)
.WithMany(p => p.DepartmentFunctions)
.HasForeignKey(d => d.FunctionId)
.OnDelete(DeleteBehavior.ClientSetNull);
I have also seen this solution, however, implementing this one would involve changing hundreds of references.

EF Core 6 error "System.ArgumentNullException: Value cannot be null. (Parameter 'key')" using API method POST and PUT

I have an error "Value cannot be null (Parameter key)" using post and put methods.
So I have to send data using a Radzen Blazor dialog
I found that my many to many relationships between (product and predefinedElements), (markets and predefinedElements) and (actuation type and predefinedelements) cause "value cannot be null" exception but I can't find what's null here...
Here is how market, predefinedElements, products and actuationType are defined in the Model
Market :
namespace BTNLib.Shared.Models
{
public partial class Market
{
public Market()
{
PredefinedElements = new HashSet<PredefinedElement>();
}
[Key]
public int MarketId { get; set; }
public string? Name { get; set; }
[InverseProperty(nameof(PredefinedElement.Markets))]
public virtual ICollection<PredefinedElement> PredefinedElements { get; set; }
}
}
PredefinedElement :
namespace BTNLib.Shared.Models
{
public partial class PredefinedElement
{
public PredefinedElement()
{
ActuationTypes = new HashSet<ActuationType>();
Markets = new HashSet<Market>();
Products = new HashSet<Product>();
}
public string? SpoolRSideStd { get; set; }
[Key]
public int PredefinedElementId { get; set; }
public string? Designation { get; set; }
public string? ConfigFileLink { get; set; }
public string? SpoolRSideRs15Rs12 { get; set; }
public string? SpoolRSideRs12Rs08 { get; set; }
public int? SectionElementPositionId { get; set; }
public int? MaxFlow { get; set; }
public int? SectionElementTypeId { get; set; }
public string? InternalPilotOilSupply { get; set; }
public int? SectionBasicFunctionId { get; set; }
public int? SectionMouvmeentNamingId { get; set; }
public int? SectionCustomerPipingId { get; set; }
public string? PortType { get; set; }
public string? ConnectorType { get; set; }
public string? Voltage { get; set; }
public string? RpnSide { get; set; }
public int? SliceTypeId { get; set; }
public string? ShortInformation { get; set; }
public string? LongInformation { get; set; }
public string? Docupedia { get; set; }
public string? SectionPicture { get; set; }
public string? SectionPictureAxo { get; set; }
public string? MasterConfigFile { get; set; }
public string? Color { get; set; }
public int? EfatemplateId { get; set; }
public int? EfaAsmTemplateId { get; set; }
public int? EfaAgzTemplateId { get; set; }
public int? EfaGezTemplateId { get; set; }
public int? TieRodThicknessSide1 { get; set; }
public int? LThreadUnderNutSide1 { get; set; }
public int? LThreadAfterNutSide1 { get; set; }
public int? NutThicknessSide1 { get; set; }
public int? InitialAnchorLenghSide1 { get; set; }
public int? LThreadUnderNutSide2 { get; set; }
public int? LThreadAfterNutSide2 { get; set; }
public int? NutThicknessSide2 { get; set; }
public int? InitialAnchorLenghSide2 { get; set; }
public int? FlangeFaceInCavityId { get; set; }
public int? FlangeFaceOut1CavityId { get; set; }
public int? FlangeFaceOut2CavityId { get; set; }
public int? RequiredFlangeFaceCavity1id { get; set; }
public int? RequiredFlangeFaceCavity2id { get; set; }
public int? RequiredFlangeFaceCavity3id { get; set; }
public int? RequiredFlangeFaceCavity4id { get; set; }
public int? RequiredFlangeFaceCavity5id { get; set; }
public int? RequiredFlangeFaceCavity6id { get; set; }
public int? RequiredFlangeFaceCavity7id { get; set; }
public int? ImageId { get; set; }
public string? Actuation { get; set; }
public virtual EfaAgzTemplate? EfaAgzTemplate { get; set; }
public virtual EfaAsmTemplate? EfaAsmTemplate { get; set; }
public virtual EfaGezTemplate? EfaGezTemplate { get; set; }
public virtual Efatemplate? Efatemplate { get; set; }
public virtual Cavity? FlangeFaceInCavity { get; set; }
public virtual Cavity? FlangeFaceOut1Cavity { get; set; }
public virtual Cavity? FlangeFaceOut2Cavity { get; set; }
public virtual Image? Image { get; set; }
public virtual Cavity? RequiredFlangeFaceCavity1 { get; set; }
public virtual Cavity? RequiredFlangeFaceCavity2 { get; set; }
public virtual Cavity? RequiredFlangeFaceCavity3 { get; set; }
public virtual Cavity? RequiredFlangeFaceCavity4 { get; set; }
public virtual Cavity? RequiredFlangeFaceCavity5 { get; set; }
public virtual Cavity? RequiredFlangeFaceCavity6 { get; set; }
public virtual Cavity? RequiredFlangeFaceCavity7 { get; set; }
public virtual SectionBasicFunction? SectionBasicFunction { get; set; }
public virtual SectionCustomerPiping? SectionCustomerPiping { get; set; }
public virtual SectionElementPosition? SectionElementPosition { get; set; }
public virtual SectionElementType? SectionElementType { get; set; }
public virtual SectionMouvementNaming? SectionMouvmeentNaming { get; set; }
public virtual SliceType? SliceType { get; set; }
[InverseProperty(nameof(ActuationType.PredefinedElements))]
public virtual ICollection<ActuationType> ActuationTypes { get; set; }
[InverseProperty(nameof(Market.PredefinedElements))]
public virtual ICollection<Market> Markets { get; set; }
[InverseProperty(nameof(Product.PredefinedElements))]
public virtual ICollection<Product> Products { get; set; }
}
}
Product :
namespace BTNLib.Shared.Models
{
public partial class Product
{
public Product()
{
PredefinedElements = new HashSet<PredefinedElement>();
}
[Key]
public int ProductsId { get; set; }
public string? Name { get; set; }
[InverseProperty(nameof(PredefinedElement.Products))]
public virtual ICollection<PredefinedElement> PredefinedElements { get; set; }
}
}
Actuation Type :
namespace BTNLib.Shared.Models
{
public partial class ActuationType
{
public ActuationType()
{
PredefinedElements = new HashSet<PredefinedElement>();
}
[Key]
public int ActuationTypeId { get; set; }
public string? Type { get; set; }
[InverseProperty(nameof(PredefinedElement.ActuationTypes))]
public virtual ICollection<PredefinedElement> PredefinedElements { get; set; }
}
}
The database context is too long to be posted here if you need it I can post it in repsonse.
When I send the data of the predefinedElement is like that :
protected async Task Submit()
{
if (Designation == null)
{
await PredefinedElementService.CreatePredefinedElement(predefinedElement);
}
else
{
await PredefinedElementService.UpdatePredefinedElement(predefinedElement);
}
}
void OnChangeMarket(IEnumerable<Market> values)
{
predefinedElement.Markets.Clear();
foreach(var Market in values)
{
predefinedElement.Markets.Add(Market);
}
}
void OnChangeProduct(IEnumerable<Product> values)
{
predefinedElement.Products.Clear();
foreach(var Product in values)
{
predefinedElement.Products.Add(Product);
}
}
void OnChangeActuationType(IEnumerable<ActuationType> values)
{
predefinedElement.ActuationTypes.Clear();
foreach(var ActuationType in values)
{
predefinedElement.ActuationTypes.Add(ActuationType);
}
}
It calls Post or Put method via a service like that :
public async Task CreatePredefinedElement(PredefinedElement predefinedElement)
{
var result = await _http.PostAsJsonAsync("api/PredefinedElements",
predefinedElement);
Console.WriteLine(result);
await SetPredefinedElement(result);
}
public async Task UpdatePredefinedElement(PredefinedElement predefinedElement)
{
var result = await
_http.PutAsJsonAsync($"api/PredefinedElements/{predefinedElement.PredefinedElementId}",
predefinedElement);
await SetPredefinedElement(result);
}
And the controller API is something like that :
The error is displayed when _context.Add or _context.Update are called
[HttpPost]
public async Task<ActionResult<List<PredefinedElement>>>
PostPredefinedElement(PredefinedElement predefinedElements)
{
try
{
_dbContext.PredefinedElements.Add(predefinedElements);
}
catch(Exception ex)
{
throw ex;
}
await _dbContext.SaveChangesAsync();
return Ok(await GetdbPredefinedElement());
}
[HttpPut("{id}")]
public async Task<ActionResult<List<PredefinedElement>>>
UpdatePredefinedElement(PredefinedElement predefinedElement)
{
if (predefinedElement == null)
{
return NotFound("Aucun element de ce type");
}
else
{
_dbContext.Update(predefinedElement);
}
await _dbContext.SaveChangesAsync();
return Ok(await GetdbPredefinedElement());
}
private async Task<List<PredefinedElement>> GetdbPredefinedElement()
{
var result = await _dbContext.PredefinedElements.Include(p => p.Products)
.Include(p => p.Markets)
.Include(p => p.ActuationTypes)
.Include(p => p.Image)
.Include(p => p.SectionElementPosition)
.Include(p => p.SectionElementType)
.Include(p => p.SectionBasicFunction)
.Include(p => p.SectionMouvmeentNaming)
.Include(p => p.SectionCustomerPiping)
.Include(p => p.SliceType)
.Include(p => p.Efatemplate)
.Include(p => p.EfaAgzTemplate)
.Include(p => p.EfaAsmTemplate)
.Include(p => p.EfaGezTemplate)
.Include(p => p.FlangeFaceInCavity)
.Include(p => p.FlangeFaceOut1Cavity)
.Include(p => p.RequiredFlangeFaceCavity1)
.Include(p => p.RequiredFlangeFaceCavity2)
.Include(p => p.RequiredFlangeFaceCavity3)
.Include(p => p.RequiredFlangeFaceCavity4)
.Include(p => p.RequiredFlangeFaceCavity5)
.Include(p => p.RequiredFlangeFaceCavity6)
.Include(p => p.RequiredFlangeFaceCavity7).ToListAsync();
return result;
}
I can't figure out what cause the exception I only know that came from many to many relationships because when I don't add entity from this relationship in the collection there are no error displayed.
I tried everything like putting [key] everywhere in the model checking my DB if there was no problem.
This project is a merge from 2 projects so there is another database context where 2 tables are linked with the first context.
EDIT : the error only happens when I try to post another predefinedelement entity or modify one resulting two entities of predefinedelement have the same entity from the table Market, Product or ActuationType.
Exemple in the Joining Table Predefinedelement_Market
PredefinedElementId : 1 MarketId : 1
and
PredefinedElementId : 2 MarketId : 1
causing the error in Entity Framework
Thanks for the help.
SOLVED:
So to prevent this error you need to had to the controller before adding the element and saving :
predefinedElements.Markets = _dbContext.Markets.Where(x => predefinedElements.Markets.Contains(x)).ToList();
predefinedElements.Products = _dbContext.Products.Where(x => predefinedElements.Products.Contains(x)).ToList();
predefinedElements.ActuationTypes = _dbContext.ActuationTypes.Where(x => predefinedElements.ActuationTypes.Contains(x)).ToList();

Lambda how to get ThenInclude at the same time in dbcontext

I have 4 classes in dbcontext,it's EventRemind.cs Event.cs House.cs Customer.cs,the code like this:
public class EventRemind
{
[Key]
public Guid Id { get; set; }
public Guid CustomerEventId { get; set; }
public DateTime RemindTime { get; set; }
public bool HasRead { get; set; }
public DateTime CreatedTime { get; set; }
[ForeignKey("CustomerEventId")]
public virtual Event CustomerEvent { get; set; }
}
public class Event
{
[Key]
public Guid Id { get; set; }
public string Title { get; set; }
public int UserId { get; set; }
public int HouseId { get; set; }
[MaxLength(800)]
public string Content { get; set; }
public DateTime CreatedTime { get; set; }
[ForeignKey("HouseId")]
public virtual House House { get; set; }
[ForeignKey("UserId")]
public virtual Customer Customer { get; set; }
public virtual ICollection<EventRemind> EventReminds { get; set; }
}
public class House
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Event> HouseEvents { get; set; }
}
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Event> CustomerEvents { get; set; }
}
and my dbcontext is this:
public class DataContext:DbContext
{
public DataContext(DbContextOptions options) : base(options)
{
}
public DbSet<EventRemind> EventReminds { get; set; }
public DbSet<Event> Events { get; set; }
public DbSet<House> Houses { get; set; }
public DbSet<Customer> Customers { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
}
that means an eventRemind include an event,an event include a house and a customer,now what puzzles me is that what should I do to get the House and Customer at the same time from EventReminds,what I want is this:
var query = _dataContext.EventReminds.Include(c => c.CustomerEvent)
.ThenInclude(c => c.Customer).ThenInclude(c => c.House //this get a compile error);
why dis this happen? Can somebody help me? Thanks in advance.
I think your last operator should be just Include. Try this:
var query = _dataContext.EventReminds
.Include(c => c.CustomerEvent)
.ThenInclude(c => c.Customer)
.Include(c => c.House);
You have to write code following way.
Way1
var query =
_dataContext.EventReminds.Include(c => c.CustomerEvent).ThenInclude(c => c.Customer)
.Include(c=> c.CustomerEvent).ThenInclude(c => c.House);
Way2 (If property is not collection then it is usefull)
var query =
_dataContext.EventReminds.Include(c=> c.CustomerEvent).
.Include(c=> c.CustomerEvent.Customer)
.Include(c=> c.CustomerEvent.House);

EF Core 3 Scaffolding (Database first) does not generate Primary Key Fluent API

I have scoffeled all my models for the project from an existing database, using EntityFramework's Scaffold-DbContext command.
EntityFramework did a perfect job in creating all of the models mapped to a table and generating the Fluent API fonfiguration code.
From what I have noticed, the Fluent API code is missing the configuration of the Primary Key field, although it has added the propery to the generated model.
Here is an example of one of my generated classes and its corresponding Fluent API code:
public partial class Account
{
public int AccountId { get; set; } //Primary Key
public int CompanyId { get; set; }
public int CompanyAccountTypeId { get; set; }
public int? CompanyAccountGroupId { get; set; }
public int? RegionId { get; set; }
public string Name { get; set; }
public string Code { get; set; }
public string Address { get; set; }
public string Email { get; set; }
public string IncludeEscalationEmail { get; set; }
public decimal? Gpslat { get; set; }
public decimal? Gpslong { get; set; }
public string Telephone { get; set; }
public string Vatnumber { get; set; }
public bool AutoReceive { get; set; }
public bool AutoIssue { get; set; }
public bool? IsBillableToAccount { get; set; }
public DateTime? BillingStart { get; set; }
public bool? IsEquipmentDepot { get; set; }
public bool? IsShiftAttendanceEnabled { get; set; }
public int? ShiftMinHoursForLunchDeduction { get; set; }
public TimeSpan? NightShiftStart { get; set; }
public TimeSpan? NightShiftEnd { get; set; }
public int? ShiftStartDayOfMonth { get; set; }
public TimeSpan? OperatingHoursStart { get; set; }
public TimeSpan? OperatingHoursEnd { get; set; }
public int? LoadBays { get; set; }
public int? LoadInterval { get; set; }
public int? ArrivalInterval { get; set; }
public TimeSpan? OverrideStockTakeCloseBalanceTime { get; set; }
public bool? TempIgnoreVendorIssueViaSap { get; set; }
public bool Archived { get; set; }
public DateTime CreatedDate { get; set; }
public int CreatedByPersonId { get; set; }
public DateTime UpdatedDate { get; set; }
public int UpdatedByPersonId { get; set; }
public virtual Company Company { get; set; }
public virtual CompanyAccountGroup CompanyAccountGroup { get; set; }
public virtual CompanyAccountType CompanyAccountType { get; set; }
public virtual Region Region { get; set; }
public virtual ICollection<AccountBalance> AccountBalance { get; set; }
public virtual ICollection<AccountContact> AccountContact { get; set; }
public virtual ICollection<AccountEquipment> AccountEquipment { get; set; }
public virtual ICollection<AccountHrlookup> AccountHrlookup { get; set; }
public virtual ICollection<AccountPickVolumeDefault> AccountPickVolumeDefaultAccount { get; set; }
public virtual ICollection<AccountPickVolumeDefault> AccountPickVolumeDefaultPartnerAccount { get; set; }
public virtual ICollection<AccountPickVolumeDetail> AccountPickVolumeDetail { get; set; }
public virtual ICollection<AccountPickVolumePartner> AccountPickVolumePartner { get; set; }
public virtual ICollection<AppUserAccount> AppUserAccount { get; set; }
public virtual ICollection<BiometricTerminal> BiometricTerminal { get; set; }
public virtual ICollection<CompanyVendorAccount> CompanyVendorAccount { get; set; }
public virtual ICollection<EquipmentCheck> EquipmentCheckAccount { get; set; }
public virtual ICollection<EquipmentCheck> EquipmentCheckAccountMaintenance { get; set; }
public virtual ICollection<GantryTransfer> GantryTransferCreditAccount { get; set; }
public virtual ICollection<GantryTransfer> GantryTransferDebitAccount { get; set; }
public virtual ICollection<Order> OrderDepotAccount { get; set; }
public virtual ICollection<Order> OrderPrimaryAccount { get; set; }
public virtual ICollection<Rfequipment> Rfequipment { get; set; }
public virtual ICollection<RfmoveTransaction> RfmoveTransactionPartnerAccount { get; set; }
public virtual ICollection<RfmoveTransaction> RfmoveTransactionPrimaryAccount { get; set; }
public virtual ICollection<ShiftCalendar> ShiftCalendar { get; set; }
public virtual ICollection<ShiftSchedule> ShiftSchedule { get; set; }
public virtual ICollection<ShiftTeam> ShiftTeam { get; set; }
public virtual ICollection<TransferDeviance> TransferDevianceIssueAccount { get; set; }
public virtual ICollection<TransferDeviance> TransferDevianceIssuePartnerAccount { get; set; }
public virtual ICollection<TransferDeviance> TransferDevianceReceiptAccount { get; set; }
public virtual ICollection<TransferDeviance> TransferDevianceReceiptPartnerAccount { get; set; }
public virtual ICollection<TransferJournal> TransferJournalCreditAccount { get; set; }
public virtual ICollection<TransferJournal> TransferJournalDebitAccount { get; set; }
public virtual ICollection<Transfer> TransferPartnerAccount { get; set; }
public virtual ICollection<Transfer> TransferPrimaryAccount { get; set; }
public virtual ICollection<VehicleCheckIn> VehicleCheckIn { get; set; }
public virtual ICollection<XAppUserAccountAccess> XAppUserAccountAccess { get; set; }
}
Here is the Fluent API:
builder.HasIndex(e => new { e.AccountId, e.CompanyAccountTypeId, e.Name, e.Code, e.CompanyId })
.HasName("IX_AccountCompanyType");
builder.HasIndex(e => new { e.Archived, e.AccountId, e.UpdatedDate, e.CompanyId, e.CompanyAccountTypeId, e.CompanyAccountGroupId, e.RegionId })
.HasName("IX_AppUserAccountAccess");
builder.HasIndex(e => new { e.AccountId, e.CompanyId, e.CompanyAccountGroupId, e.RegionId, e.Name, e.Gpslong, e.BillingStart, e.Code, e.Address, e.Email, e.IncludeEscalationEmail, e.Gpslat, e.ArrivalInterval, e.Telephone, e.Vatnumber, e.AutoReceive, e.AutoIssue, e.IsBillableToAccount, e.UpdatedDate, e.IsEquipmentDepot, e.OperatingHoursStart, e.OperatingHoursEnd, e.LoadBays, e.LoadInterval, e.UpdatedByPersonId, e.OverrideStockTakeCloseBalanceTime, e.TempIgnoreVendorIssueViaSap, e.Archived, e.CreatedDate, e.CreatedByPersonId, e.CompanyAccountTypeId })
.HasName("IX_vAccount");
builder.Property(e => e.Address)
.HasMaxLength(500)
.IsUnicode(false);
builder.Property(e => e.BillingStart).HasColumnType("date");
builder.Property(e => e.Code)
.HasMaxLength(50)
.IsUnicode(false);
builder.Property(e => e.CreatedByPersonId).HasColumnName("CreatedBy_PersonId");
builder.Property(e => e.CreatedDate).HasColumnType("datetime");
builder.Property(e => e.Email)
.HasMaxLength(200)
.IsUnicode(false);
builder.Property(e => e.Gpslat)
.HasColumnName("GPSLat")
.HasColumnType("decimal(18, 6)");
builder.Property(e => e.Gpslong)
.HasColumnName("GPSLong")
.HasColumnType("decimal(18, 6)");
builder.Property(e => e.IncludeEscalationEmail)
.HasMaxLength(500)
.IsUnicode(false);
builder.Property(e => e.Name)
.IsRequired()
.HasMaxLength(255)
.IsUnicode(false);
builder.Property(e => e.Telephone)
.HasMaxLength(20)
.IsUnicode(false);
builder.Property(e => e.TempIgnoreVendorIssueViaSap).HasColumnName("temp_IgnoreVendorIssueViaSAP");
builder.Property(e => e.UpdatedByPersonId).HasColumnName("UpdatedBy_PersonId");
builder.Property(e => e.UpdatedDate).HasColumnType("datetime");
builder.Property(e => e.Vatnumber)
.HasColumnName("VATNumber")
.HasMaxLength(50)
.IsUnicode(false);
builder.HasOne(d => d.CompanyAccountGroup)
.WithMany(p => p.Account)
.HasForeignKey(d => d.CompanyAccountGroupId)
.HasConstraintName("FK_Account_CompanyAccountGroup");
builder.HasOne(d => d.CompanyAccountType)
.WithMany(p => p.Account)
.HasForeignKey(d => d.CompanyAccountTypeId)
.OnDelete(DeleteBehavior.ClientSetNull)
.HasConstraintName("FK_Account_CompanyAccountType");
builder.HasOne(d => d.Company)
.WithMany(p => p.Account)
.HasForeignKey(d => d.CompanyId)
.OnDelete(DeleteBehavior.ClientSetNull)
.HasConstraintName("FK_Account_Company");
builder.HasOne(d => d.Region)
.WithMany(p => p.Account)
.HasForeignKey(d => d.RegionId)
.HasConstraintName("FK_Account_Region");
As you can see, my model has the Primary Key field named AccountId. Why does the mapping for this not get added in the Fluent API code?
It's not being added, because it's a convention that this property is the primary key.
From Conventions in Entity Framework Core:
If a property is named ID or <entity name>ID (not case-sensitive), it will be configured as the primary key. Entity Framework Core will prefer ID over <entity name>ID in the event that a class contains both.

ArgumentNullException: Value cannot be null. Parameter name: key on Include Statement

Worked a lot with EF 6.x (via designer) and now started on a new project using EF Core.
I'm getting an error that says value cannot be null, not sure exactly what I'm doing wrong. I've got rid of a lot of fields for brevity as there are hundreds.
All these tables are views via synonyms that connect to a different database. I can get it to work fine, if I do each individual call to a database, but as soon as I do include. I get an error on that line. The error I'm getting is
ArgumentNullException: Value cannot be null.
Parameter name: key
System.Collections.Generic.Dictionary.FindEntry(TKey key)
OnGetAsync
var equipment = _context.EMEMs.Include(x => x.EMEDs).Where(x => x.KeyID.ToString() == key);
EMEM = await equipment.Include(x => x.EMCM).ThenInclude(x=>x.EMCDs).FirstOrDefaultAsync();
EMEM
public class EMEM
{
public byte? EMCo { get; set; }
[Display(Name = "Equipment Code")]
public string Equipment { get; set; }
public string Type { get; set; }
public string Category { get; set; }
public Guid? UniqueAttchID { get; set; }
[Key]
public long KeyID { get; set; }
[NotMapped] public string EquipmentDetails => $"{Equipment.Trim()} - {Description} - {VINNumber}";
public virtual IEnumerable<EMWH> EMWHs { get; set; }
public virtual EMCM EMCM { get; set; }
public virtual IEnumerable<udEMED> EMEDs { get; set; }
}
EMCM
public class EMCM
{
[Key]
public long KeyID { get; set; }
public byte? EMCo { get; set; }
public string Category { get; set; }
public string Description { get; set; }
public string Notes { get; set; }
public virtual IEnumerable<EMEM> EMEMs { get; set; }
public virtual IEnumerable<udEMCD> EMCDs { get; set; }
}
udEMCD
public class udEMCD
{
[Key]
public long KeyID { get; set; }
public byte? Co { get; set; }
public string Category { get; set; }
public string DocumentCategory { get; set; }
public int Seq { get; set; }
public Guid? UniqueAttchID { get; set; }
public virtual udEMDC EMDC { get; set; }
public virtual EMCM EMCM { get; set; }
public virtual IEnumerable<HQAT> HQATs { get; set; }
}
Context
modelBuilder.Entity<EMEM>().ToTable("EMEM").HasOne(x => x.EMCM).WithMany(x => x.EMEMs).HasForeignKey(x => new { x.EMCo, x.Category }).HasPrincipalKey(x => new { x.EMCo, x.Category });
modelBuilder.Entity<EMEM>().ToTable("EMEM").HasMany(x => x.EMEDs).WithOne(x => x.EMEM).HasForeignKey(x => new { x.Co, x.Equipment }).HasPrincipalKey(x => new { x.EMCo, x.Equipment });
modelBuilder.Entity<EMCM>().ToTable("EMCM").HasMany(x => x.EMCDs).WithOne(x => x.EMCM)
.HasForeignKey(x => new { x.Co, x.Category }).HasPrincipalKey(x => new { x.EMCo, x.Category });
modelBuilder.Entity<udEMCD>().ToTable("udEMCD").HasOne(x => x.EMDC).WithMany(x => x.EMCDs)
.HasForeignKey(x => x.DocumentCategory).HasPrincipalKey(x => x.Category);
modelBuilder.Entity<udEMDC>().ToTable("udEMDC").HasMany(x => x.EMEDs).WithOne(x => x.EMDC).HasForeignKey(x => new{ x.DocumentCategory}).HasPrincipalKey(x => new{ x.Category});
modelBuilder.Entity<udEMED>().ToTable("udEMED");
modelBuilder.Entity<EMWH>().ToTable("EMWH");
modelBuilder.Entity<EMWI>().ToTable("EMWI");
modelBuilder.Entity<HQAT>().HasOne(x => x.EMWH).WithMany(x => x.HQATs).HasForeignKey(x => x.UniqueAttchID)
.HasPrincipalKey(x => x.UniqueAttchID);
modelBuilder.Entity<EMWH>().HasOne(x => x.EMEM).WithMany(x => x.EMWHs)
.HasForeignKey(x => new {x.EMCo, x.Equipment}).HasPrincipalKey(x => new {x.EMCo, x.Equipment});
EDIT: I added nullable KeyID's just to test prior to uploading and still didn't work.
I think the error is that you're declaring the Key as nullable, which it should never happen.
[Key]
public long? KeyID { get; set; }
change your code to this...
[Key]
public long KeyID { get; set; }

Categories

Resources