Entity Framework - Code First - Multiplicity constraint violated, The role X of the relationship Y has multiplicity 1 or 0..1 - entity-framework

Using code first (EF 6), I created a 1 parent - 2 child relationship. Property is the parent object and Property Address as a child with 1 or 0..1 relationship. PropertyImage is another child with 1 to many relationship. PropertyImage works fine but the PropertyAddress throws error if I try to eager load .
Actual Error -
Multiplicity constraint violated.
The role 'PropertyAddress_Property_Source' of the relationship 'MyAssetTracker.DataLayer.Models.PropertyAddress_Property' has multiplicity 1 or 0..1.
// Test Function
GetProperty()
{
Property property;
using (var repo = new PropertyRepository())
{
property = repo.AllIncluding(a=>a.Images, a=>a.Address).FirstOrDefault(a => a.Id == testpropertyid);
}
}
//Property Repository
public class PropertyRepository : IPropertyRepository
{
public IQueryable<Property> AllIncluding(params Expression<Func<Property, object>>[] includeProperties)
{
IQueryable<Property> query = context.Properties;
foreach (var includeProperty in includeProperties) {
query = query.Include(includeProperty);
}
return query;
}
}
//Property Entity
public class Property : DomainModelAuditBase, IDomainModelState
{
private Address _address;
private ICollection<Asset> _assets;
private ICollection<PropertyImage> _images;
public Property()
{
_address = new Address();
_assets = new List<Asset>();
_images = new List<PropertyImage>();
}
public Guid Id { get; set; }
[StringLength(100), Required]
public string Title { get; set; }
public bool IsPrimary { get; set; }
[StringLength(255)]
public string Description { get; set; }
[NotMapped]
public State State { get; set; }
public Guid AddressId { get; set; }
public Guid UserId { get; set; }
public virtual Address Address
{
get { return _address; }
set { _address = value; }
}
public virtual ICollection<Asset> Assets
{
get { return _assets; }
set { _assets = value; }
}
public virtual User User { get; set; }
public virtual ICollection<PropertyImage> Images
{
get { return _images; }
set { _images = value; }
}
}
//PropertyAddress
public class Address : DomainModelAuditBase, IDomainModelState
{
[Key,ForeignKey("Property")]
public Guid PropertyId { get; set; }
[StringLength(255),Required]
public string AddressLine1 { get; set; }
[StringLength(255)]
public string AddressLine2 { get; set; }
[StringLength(255)]
public string City { get; set; }
[StringLength(255)]
public string StateProvince { get; set; }
[StringLength(100)]
public string PostalCode { get; set; }
[StringLength(100)]
public string Country { get; set; }
[NotMapped]
public State State { get; set; }
public virtual Property Property { get; set; }
}

Remove_address = new Address(); from Property constructor.
You could read about similar problem here
Also are you sure that you need AddressId field in Property class?

Related

EF Core 6: Reading two tables using navigations doesn't load child table data

The role property of a relation record doesn't get read/initialized (i.e. the data from the included table doesn't get read). Why is that? The data is in the database.
public class IDM_Role
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
public long role_id { get; set; } = -1;
[StringLength(80)]
public string role_name { get; set; } = string.Empty;
}
public class IDM_Relation
{
[Required]
[StringLength(80)]
public string account_id { get; set; } = string.Empty;
[Required]
[ForeignKey("IDM_Role")]
public long role_id { get; set; } = 0;
[ForeignKey("role_id")]
public virtual IDM_Role role { get; set; }
}
modelBuilder.Entity<IDM_Relation>()
.HasKey(e => new { e.role_id, e.account_id })
.HasName("PK_IDM_Relation");
[EnableQuery(PageSize = 15)]
public IQueryable<IDM_Relation> Get()
{
return _context.idm_relations.Include(e => e.role);
}
Removing "virtual" from the property IDM_Role role doesn't help.

Entity Framwork Update many to many

I am new to ef core. I am trying to implement many to many .
Here is my DBContext
public class MaxCiSDbContext : DbContext
{
public DbSet<Job> Jobs { get; set; }
public DbSet<Staff> Staffs { get; set; }
public MaxCiSDbContext(DbContextOptions<MaxCiSDbContext> options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Job>()
.HasMany(t => t.Staffs)
.WithMany(t => t.Jobs);
base.OnModelCreating(modelBuilder);
}
}
and Here is my Staff Class
public class Staff
{
public string Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public string Mobile { get; set; }
public string Address { get; set; }
//Navigation
public virtual ICollection<Job> Jobs { get; set; }
}
Here is my Job Class
public class Job
{
[Key]
public string Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string State { get; set; }
public string ClientOrderNumber { get; set; }
public string StartDate { get; set; }
public string DueDate { get; set; }
public string CompletedDate { get; set; }
public string ClientId { get; set; }
public string ManagerId { get; set; }
public string PartnerId { get; set; }
//Navigation
public virtual ICollection <Staff> Staffs { get; set; }
}
I Call an API which returns a XmlDocument, I read that document and update database.
Here is how I deal with xmldocument.
//Fetch Current Jobs and populate to DB
XmlDocument apiresults = JobMethods.GetCurrent();
XmlNodeList nodes = apiresults.DocumentElement.SelectNodes("/Response/Jobs/Job");
foreach (XmlNode node in nodes)
{
Job MaxCiSJob = new Job()
{
Id = node.SelectSingleNode("ID").InnerText,
Name = node.SelectSingleNode("Name").InnerText,
Description = node.SelectSingleNode("Description").InnerText,
State = node.SelectSingleNode("State").InnerText,
ClientOrderNumber = node.SelectSingleNode("ClientOrderNumber").InnerText,
StartDate = node.SelectSingleNode("StartDate").InnerText,
DueDate = node.SelectSingleNode("DueDate") != null ? node.SelectSingleNode("DueDate").InnerText : "",
CompletedDate = node.SelectSingleNode("CompletedDate") != null ? node.SelectSingleNode("CompletedDate").InnerText : "",
ClientId = node.SelectSingleNode("Client/ID").InnerText,
ManagerId = node.SelectSingleNode("Manager/ID") != null ? node.SelectSingleNode("Manager/ID").InnerText : "",
PartnerId = node.SelectSingleNode("Partner") != null ? node.SelectSingleNode("Partner").InnerText : ""
};
XmlNodeList Assigned = node.SelectNodes("Assigned/Staff");
MaxCiSJob.Staffs = new Collection<Staff>();
foreach (XmlNode staffNode in Assigned)
{
var staffId = staffNode.SelectSingleNode("ID").InnerText;
var staff = _db.Staffs.Find(staffId);
if(staff != null)
{
MaxCiSJob.Staffs.Add(staff);
}
}
if (_db.Jobs.Find(MaxCiSJob.Id) == null)
{
//Insert Record
_db.Jobs.Add(MaxCiSJob);
}
else
{
// UPDATE recorde
_db.Jobs.Update(MaxCiSJob);
}
}
_db.SaveChanges();
}
Everything works well when I run the program for the first time(The linking table ,"JobStaff", is empty) but when I run the Program for the second time I get an excetpion:
SqlException: Violation of PRIMARY KEY constraint 'PK_JobStaff'. Cannot insert duplicate key in object 'dbo.JobStaff'. The duplicate key value is (J14995, 557898).
Can someone please help me on how can I resolve this issue.
Running your code EF core wants to add entities anyway. Because your entities are not attached.
Try this code:
//Fetch Current Jobs and populate to DB
XmlDocument apiresults = JobMethods.GetCurrent();
XmlNodeList nodes = apiresults.DocumentElement.SelectNodes("/Response/Jobs/Job");
foreach (XmlNode node in nodes)
{
var id = node.SelectSingleNode("ID").InnerText;
Job MaxCiSJob = _db.Jobs.Find(id);
if (MaxCiSJob == null)
{
MaxCiSJob = new Job() { Id = id };
_db.Jobs.Add(MaxCiSJob);
}
MaxCiSJob.Name = node.SelectSingleNode("Name").InnerText;
MaxCiSJob.Description = node.SelectSingleNode("Description").InnerText;
MaxCiSJob.State = node.SelectSingleNode("State").InnerText;
MaxCiSJob.ClientOrderNumber = node.SelectSingleNode("ClientOrderNumber").InnerText;
MaxCiSJob.StartDate = node.SelectSingleNode("StartDate").InnerText;
MaxCiSJob.DueDate = node.SelectSingleNode("DueDate") != null ? node.SelectSingleNode("DueDate").InnerText : "";
MaxCiSJob.CompletedDate = node.SelectSingleNode("CompletedDate") != null ? node.SelectSingleNode("CompletedDate").InnerText : "";
MaxCiSJob.ClientId = node.SelectSingleNode("Client/ID").InnerText;
MaxCiSJob.ManagerId = node.SelectSingleNode("Manager/ID") != null ? node.SelectSingleNode("Manager/ID").InnerText : "";
MaxCiSJob.PartnerId = node.SelectSingleNode("Partner") != null ? node.SelectSingleNode("Partner").InnerText : "";
XmlNodeList Assigned = node.SelectNodes("Assigned/Staff");
foreach (XmlNode staffNode in Assigned)
{
MaxCiSJob.Staffs.Clear();
var staffId = staffNode.SelectSingleNode("ID").InnerText;
var staff = _db.Staffs.Find(staffId);
if (staff != null)
{
MaxCiSJob.Staffs.Add(staff);
}
}
}
_db.SaveChanges();
And you should change your domains this way in order not to get NullReferenceException:
public class Staff
{
public string Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public string Mobile { get; set; }
public string Address { get; set; }
//Navigation
public virtual ICollection<Job> Jobs { get; set; } = new Collection<Job>();
}
public class Job
{
[Key]
public string Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string State { get; set; }
public string ClientOrderNumber { get; set; }
public string StartDate { get; set; }
public string DueDate { get; set; }
public string CompletedDate { get; set; }
public string ClientId { get; set; }
public string ManagerId { get; set; }
public string PartnerId { get; set; }
//Navigation
public virtual ICollection<Staff> Staffs { get; set; } = new Collection<Staff>();
}

Could not find the implementation of the query pattern for source type. Join not found

I don't know if I am doing this right. I have 2 tables Property and PropertyTypes. Each Property has 1 PropertyType. I am using a foreign key constraint. But on the creation of the controller, I get this error already:
"Could not find an implementation of the query pattern for source type 'DbSet'.'Join not found'
Please see my code below:
[Table("Property.Property")]
public class Property
{
[Key]
public int PropertyId { get; set; }
[StringLength(50)]
public string PropertyName { get; set; }
public int? Owner { get; set; }
public string Cluster { get; set; }
public string PropertyNumber { get; set; }
public string RegionCode { get; set; }
public string ProvinceCode { get; set; }
public string MunicipalCode { get; set; }
public string BarangayCode { get; set; }
public DateTime? DateAdded { get; set; }
public DateTime? DateModified { get; set; }
public int PropertyTypeId { get; set; }
public PropertyType PropertyType { get; set; }
[NotMapped]
public string Type { get; set; }
}
[Table("Property.Types")]
public class PropertyType
{
[Key]
public int PropertyTypeId { get; set; }
[StringLength(50)]
public string Type { get; set; }
public DateTime? DateAdded { get; set; }
public DateTime? DateModified { get; set; }
public List<Property> Properties { get; set; }
}
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("DefaultConnection", throwIfV1Schema: false) {}
// DB Sets
public DbSet<Property> Properties { get; set; }
public DbSet<PropertyType> PropertyTypes { get; set; }
}
Controller
public class PropertyController : ApiController
{
[HttpGet]
[Authorize]
[Route("api/getproperties")]
public async Task<List<Property>> GetProperties()
{
using(var db = new ApplicationDbContext())
{
var properties = await (from p in db.Properties
join pt in db.PropertyTypes
on p.PropertyTypeId equals pt.PropertyTypeId
select new
{
PropertyId = p.PropertyId,
PropertyName = p.PropertyName,
Owner = p.ProertyOwner,
Cluster = p.Cluster,
PropertyNumber = p.PropertyNumber,
RegionCode = p.RegionCode,
ProvinceCode = p.ProvinceCode,
MunicipalCode = p.MunicipalCode,
BarangayCode = p.BarangayCode,
DateAdded = p.DateAdded,
DateModified = p.DateModified,
PropertyTypeId = p.PropertyTypeId,
type = pt.Type
}
).ToListAsync();
return properties;
}
}
}
Can you please show me the right way to do this? Thank you.

Entity Framework mapping 2 one to many with existing DB and Model

I have been trying to update a project of my with Entity Framework. I have an existing database and model, which after some work matched. With some more work, I managed to get the application to successfully read the data from the database. But when saving new data, the nightmare started.
In my data structure, I have 2 one-to-many relations, one between player and team and one between match and team. I have been trying many configurations (with [Key], foreign key, inverse property attributes) but I either get an error
Trying to cast List to team
or
no column found Match_id no column found Player_id
This is my code:
public class Match
{
//[Key]
//[DatabaseGenerated(DatabaseGeneratedOption.None)]
public string Id { get; set; }
//[Column("Date")]
public DateTime Date { get; set; }
public DateTime EndTime { get; set; }
[NotMapped]
public bool Remove { get; set; }
//[InverseProperty("Match")]
[ForeignKey("MatchId")]
public virtual ICollection<Team> Teams { get; set; }
public int WinningTeamId { get; set; }
public MatchType MatchType { get; set; }
public string Source { get; internal set; }
public Match()
{
WinningTeamId = -1;
this.Teams = new List<Team>();
this.EndTime = (DateTime)SqlDateTime.MinValue;
}
}
public class Team
{
public int TeamId { get; set; }
[NotMapped]
public int RatingChange { get; set; }
[Key()]
[Column("PlayerId", Order = 2)]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public virtual Player Player { get; set; }
[Column(Order = 1)]
[Key()]
//[DatabaseGenerated(DatabaseGeneratedOption.None)]
public string MatchId { get; set; }
[ForeignKey("MatchId")]
public virtual Match Match { get; set; }
[NotMapped]
public int Rating { get; set; }
public Team()
{
}
}
public class Player
{
public string name { get; set; }
public int PastatsId { get; set; }
public string UberId { get; set; }
//[ForeignKey("PlayerId")]
//[InverseProperty("Player")]
public virtual ICollection<Team> Teams { get; set; }
//[Key()]
public int Id { get; set; }
}
To save the new matches, I first save the players to prevent conflicts there:
public void Save(IEnumerable<Match> matches)
{
foreach (var match in matches)
{
foreach (var team in match.Teams)
{
var entry = Entry(team.Player);
if (entry.State == EntityState.Detached)
{
var localplayer = Players.Local.FirstOrDefault(x => x.UberId == team.Player.UberId);
if (localplayer == null)
{
this.Players.Add(team.Player);
team.Player = entry.Entity;
}
else
{
team.Player = localplayer;
}
}
else
{
Entry(team.Player).State = EntityState.Modified;
}
}
}
SaveChanges();
foreach (var match in matches)
{
if (Matches.Find(match.Id) != null)
{
continue;
}
if (Entry(match).State == EntityState.Detached)
{
this.Matches.Add(match);
}
}
SaveChanges();
}
How to do this mapping with an existing database and code?
Any insight will be gratefully appreciated.

EF code first property not mapped

The problem I'm encountering is when I try to insert a new record in a ASPxGridView which is a master of detail in an asp.net page.
This only occurs when adding a new record is required when there is no record.
EnderecoEscola entity:
namespace DAL
{
[Table("CAD_ENDERECO_ESCOLA")]
public class EnderecoEscola
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ENDESC_ID { get; set; }
[Required]
public int ESCOLA_ID { get; set; }
[Association("Escolas", "ESCOLA_ID", "ESCOLA_ID")]
[ForeignKey("ESCOLA_ID")]
public virtual Escola Escola { get; set; }
[Required]
public int TPOEND_ID { get; set; }
[ForeignKey("TPOEND_ID")]
public virtual TipoEndereco TipoEndereco { get; set; }
[Required]
public int ENDESC_UF_ID { get; set; }
[ForeignKey("ENDESC_UF_ID")]
public virtual UnidadeFederativa UnidadeFederativa { get; set; }
[Required]
public int ENDESC_MUN_iD { get; set; }
[ForeignKey("ENDESC_MUN_iD")]
public virtual Municipio Municipio { get; set; }
[StringLength(10), Required]
[MinLength(8)]
public string ENDESC_CEP { get; set; }
[StringLength(100), Required]
[MinLength(10)]
public string ENDESC_ENDERECO { get; set; }
[StringLength(15)]
public string ENDESC_NRO { get; set; }
[StringLength(25)]
public string ENDESC_COMPL { get; set; }
[StringLength(70)]
public string ENDESC_BAIRRO { get; set; }
[NotMapped]
public String TPEND_DESCRICAO { get; set; }
[NotMapped]
public String UF_SIGLA { get; set; }
[NotMapped]
public String MUN_DESCRICAO { get; set; }
}
}
DAL :
namespace DAL.utilities
{
public class OperationCadEnderecoEscola
{
public IQueryable<EnderecoEscola> GetId(int idEsc)
{
using (SecurityCtx ctx = new SecurityCtx())
{
ctx.Configuration.LazyLoadingEnabled = false;
var query = ctx.EnderecoEscola.Include("TipoEndereco").Include("UnidadeFederativa").Include("Municipio").Where(w => w.ESCOLA_ID == idEsc).OrderBy(p => p.ENDESC_ENDERECO).ToList().
Select(w => new EnderecoEscola
{
ENDESC_ID = w.ENDESC_ID,
ESCOLA_ID = w.ESCOLA_ID,
TPOEND_ID = w.TPOEND_ID,
ENDESC_UF_ID = w.ENDESC_UF_ID,
ENDESC_MUN_iD = w.ENDESC_MUN_iD,
ENDESC_CEP = w.ENDESC_CEP,
ENDESC_ENDERECO = w.ENDESC_ENDERECO,
ENDESC_NRO = w.ENDESC_NRO,
ENDESC_COMPL = w.ENDESC_COMPL,
ENDESC_BAIRRO = w.ENDESC_BAIRRO,
TPEND_DESCRICAO = w.TipoEndereco.TPEND_DESCRICAO != null ? w.TipoEndereco.TPEND_DESCRICAO : w.TPEND_DESCRICAO,
UF_SIGLA = w.UnidadeFederativa.UF_SIGLA != null ? w.UnidadeFederativa.UF_SIGLA : w.UF_SIGLA,
MUN_DESCRICAO = w.Municipio.MUN_DESCRICAO != null ? w.Municipio.MUN_DESCRICAO : w.MUN_DESCRICAO
}).Distinct().AsQueryable();
return query;
}
}
}
}
When applying for inclusion in ASPxGridView a new record and the method in DAL public IQueryable <EnderecoEscola> getId (int idEsc) is invoked to retrieve the data and they do not exists it is adding a new record on the master and detail occurs error
A field or property with name 'TPEND_DESCRICAO' was not found in the
selected data source.
Someone could guide me on how to solve the problem.
Tks.