Why model in Entity Framework 6 can not serialize the data? - entity-framework

I try to get data from model and pass to client with json format. I wrote this code but when execute the code, I get an internal server error. When debugging code, data is shown such as this image.
Please advice.
[HttpPost]
public ActionResult GetCity(int idCountry)
{
TravelEnterAdminTemplate.Models.LG.MyJsonResult myresult = new Models.LG.MyJsonResult();
try
{
List<City> citylist = new List<City>();
var citystable = db.Cities.Where(p => p.CountryId == idCountry).ToList();
if (citystable != null)
{
foreach (var city in citystable)
{
myresult.obj = citystable;
}
myresult.Result = true;
}
else
{
myresult.Result = false;
myresult.message = "داده ای یافت نشد";
}
}
catch (Exception e)
{
errorlog.Error("DeleteShopping", "157", e.Source.ToString(), e.Message);
myresult.Result = false;
myresult.message = "خطا در بارگذاری اطلاعات";
}
return Json(myresult, JsonRequestBehavior.AllowGet);
}
City Entity :
namespace TravelEnterAdminTemplate.Models.dbModel
{
using System;
using System.Collections.Generic;
public partial class City
{
public City()
{
this.ArtPlaces = new HashSet<ArtPlace>();
this.Historicals = new HashSet<Historical>();
this.Hospitals = new HashSet<Hospital>();
this.Hotels = new HashSet<Hotel>();
this.PhotoTables = new HashSet<PhotoTable>();
this.PhotoTables1 = new HashSet<PhotoTable>();
this.Restaurants = new HashSet<Restaurant>();
this.Shoppings = new HashSet<Shopping>();
}
public int Id { get; set; }
public string NameFA { get; set; }
public string NameEN { get; set; }
public int CountryId { get; set; }
public virtual ICollection<ArtPlace> ArtPlaces { get; set; }
public virtual Country Country { get; set; }
public virtual ICollection<Historical> Historicals { get; set; }
public virtual ICollection<Hospital> Hospitals { get; set; }
public virtual ICollection<Hotel> Hotels { get; set; }
public virtual ICollection<PhotoTable> PhotoTables { get; set; }
public virtual ICollection<PhotoTable> PhotoTables1 { get; set; }
public virtual ICollection<Restaurant> Restaurants { get; set; }
public virtual ICollection<Shopping> Shoppings { get; set; }
}
}

Related

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>();
}

Entity Framework always adds two records in the tables

I'm implementing an ASP.NET Core 3.1 app. I have implemented following code to insert record in SQL Server database via EF Core but each time I save data, it inserts two records in PersonRequester and Requester table. I appreciate if anyone suggests me how I can prevent reinserting records.
Requester ap = new Requester();
ap.Address = RequesterViewModel.Requestervm.Address;
ap.RequesterType = RequesterViewModel.Requestervm.RequesterType;
ap.Description = RequesterViewModel.Requestervm.Description;
ap.Name = RequesterViewModel.Requestervm.Name;
var pa = new PersonRequester()
{
BirthCertificateNo = RequesterViewModel.personRequestervm.BirthCertificateNo,
IssuePlace = RequesterViewModel.personRequestervm.IssuePlace,
NationalCode = RequesterViewModel.personRequestervm.NationalCode,
Requester = ap
};
using (var context = new DBContext())
{
context.PersonRequester.Attach(pa);
try
{
context.SaveChanges();
}
catch (Exception e)
{
throw e;
}
}
public partial class Requester
{
public Requester()
{
PersonRequester = new HashSet<PersonRequester>();
}
public int RequesterId { get; set; }
public int RequesterType { get; set; }
public string Address { get; set; }
public string Description { get; set; }
public string Name { get; set; }
public virtual EntityType RequesterTypeNavigation { get; set; }
public virtual ICollection<PersonRequester> PersonRequester { get; set; }
}
public partial class PersonRequester
{
public int RequesterId { get; set; }
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public int RequesterType { get; set; }
public string NationalCode { get; set; }
public string BirthCertificateNo { get; set; }
public string IssuePlace { get; set; }
public virtual Requester Requester { get; set; }
public virtual EntityType RequesterTypeNavigation { get; set; }
}

MVC4 Entity Framework Controller Database Issue

I am trying to perform an insert or update from my controller but I get an error message stating that 'ICN.CourierClient does not contain a definition' of my various properties like 'Address' - when in fact it does, and my other similar calls to other database models work fine with the same code. Did I miss a reference or some configuration somewhere, I have it defined in the same way as my other models in my dbset statements:
public DbSet<Courier> Couriers { get; set; }
public DbSet<Driver> Drivers { get; set; }
public DbSet<Job> Jobs { get; set; }
public DbSet<CourierClient> CourierClients { get; set; }
IQueryable<Courier> Datasource.Couriers { get { return Couriers; } }
IQueryable<Driver> Datasource.Drivers { get { return Drivers; } }
IQueryable<Job> Datasource.Jobs { get { return Jobs; } }
IQueryable<CourierClient> Datasource.CourierClients { get { return CourierClients; } }
IEnumerable<CourierClient> client = null;
client = from c in db.CourierClients where c.ClientName == job.PickupCompanyName select c;
if (client != null)
{
client.Address = job.PickupAddress1;
client.City = job.PickupCity;
client.State = job.PickupState;
client.Zip = job.PickupZip;
client.Phone = job.PickupPhone;
db.Entry(client).State = EntityState.Modified;
}
else
{
client.ClientName = job.PickupCompanyName;
client.Address = job.PickupAddress1;
client.City = job.PickupCity;
client.State = job.PickupState;
client.Zip = job.PickupZip;
client.Phone = job.PickupPhone;
db.CourierClients.Add(client);
}
db.SaveChanges();
public class CourierClient
{
[Key]
public virtual int ID { get; set; }
public virtual string ClientName { get; set; }
public virtual string ContactName { get; set; }
public virtual string Address { get; set; }
public virtual string City { get; set; }
public virtual string State { get; set; }
public virtual string Zip { get; set; }
public virtual string Phone { get; set; }
public virtual string Fax { get; set; }
public virtual string Email { get; set; }
}
You declared client as IEnumerable<CourierClient>. That is why compiler tells you that it does not have properties, which you expect to find in CourierClient.
CourierClient client = (from c in db.CourierClients where c.ClientName == job.PickupCompanyName select c).SingleOrDefault();
if (client != null)
{
client.Address = job.PickupAddress1;
client.City = job.PickupCity;
client.State = job.PickupState;
client.Zip = job.PickupZip;
client.Phone = job.PickupPhone;
db.Entry(client).State = EntityState.Modified;
}
else
{
client = new CourierClient();
client.ClientName = job.PickupCompanyName;
client.Address = job.PickupAddress1;
client.City = job.PickupCity;
client.State = job.PickupState;
client.Zip = job.PickupZip;
client.Phone = job.PickupPhone;
db.CourierClients.Add(client);
}
db.SaveChanges();
Note the creation of the instance of CourierClient if it was not found.

How to write an Edit Action

I am trying to come up with an edit action. See below for what i have so far.
ViewModel:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace GlobalUnitedSC.WebUI.Models
{
public sealed class CreateMensPlayerViewModel
{
//Player profile starts here
[HiddenInput(DisplayValue=false)]
public int MensTeamId { get; set; }
[HiddenInput(DisplayValue = false)]
public int PlayerId { get; set; }
[Required]
public string Name { get; set; }
[DataType(DataType.Date)]
public DateTime? BirthDate { get; set; }
[Required]
public string Position { get; set; }
public int ShirtNumber { get; set; }
[DataType(DataType.Date)]
public DateTime? Joined { get; set; }
public string Country { get; set; }
[DataType(DataType.MultilineText)]
public string Description { get; set; }
public byte[] ImageData { get; set; }
[HiddenInput(DisplayValue = false)]
public string ImageMimeType { get; set; }
[DataType(DataType.EmailAddress)]
public string EmailAddress { get; set; }
[DataType(DataType.PhoneNumber)]
public string PhoneNumber { get; set; }
//Player Statistics starts here
public int Games { get; set; }
public int Goals { get; set; }
public int Assists { get; set; }
public int TotalShots { get; set; }
public int ShotsOnGoal { get; set; }
public int FoulsDrawn { get; set; }
public int FoulsCommitted { get; set; }
public int Saves { get; set; }
public int BlueCards { get; set; }
public int YellowCards { get; set; }
public int RedCards { get; set; }
}
}
Create Actions:
[HttpGet]
public ActionResult Create(int mensTeamId)
{
new CreateMensPlayerViewModel {MensTeamId = mensTeamId};
return View();
}
[HttpPost]
public ActionResult Create(CreateMensPlayerViewModel viewModel, HttpPostedFileBase image)
{
if (ModelState.IsValid)
{
var mensTeam = _dataSource.MensTeams.Single(t => t.Id == viewModel.MensTeamId);
var mensPlayer = new MensPlayer
{
Name = viewModel.Name,
BirthDate = viewModel.BirthDate,
Position = viewModel.Position,
ShirtNumber = viewModel.ShirtNumber,
Joined = viewModel.Joined,
Country = viewModel.Country,
Description = viewModel.Description,
EmailAddress = viewModel.EmailAddress,
PhoneNumber = viewModel.PhoneNumber,
Games = viewModel.Games,
Goals = viewModel.Goals,
Assists = viewModel.Assists,
TotalShots = viewModel.TotalShots,
ShotsOnGoal = viewModel.ShotsOnGoal,
FoulsDrawn = viewModel.FoulsDrawn,
FoulsCommitted = viewModel.FoulsCommitted,
Saves = viewModel.Saves,
BlueCards = viewModel.BlueCards,
YellowCards = viewModel.YellowCards,
RedCards = viewModel.RedCards
};
mensTeam.MensPlayers.Add(mensPlayer);
_dataSource.Save();
TempData["message"] = string.Format("{0} has been saved", mensPlayer.Name);
return RedirectToAction("detail", "MensTeam", new {id = viewModel.MensTeamId});
}
return View(viewModel);
}
HttpGet Edit Action
[HttpGet]
public ActionResult Edit (int id)
{
var mensPlayer = _dataSource.MensPlayers.FirstOrDefault(p => p.Id == id);
return View(mensPlayer);
}
Now could anyone please help me with the HttpPost Edit action, preferably one based on the model class mentioned above?
I was hoping it has something to do with the line below, if this creates a new player, what could i write to edit that player?
var mensPlayer = new MensPlayer {}
Since it's a post the method is kind of equal to your create-method. You will receive a MensPlayer as a parameter.
Than you check if the Model is valid (validation etc.) and flag the entry as modified and save the changes.
[HttpPost]
public ActionResult Edit(MyModel myModel)
{
if (ModelState.IsValid)
{
DbContext.Entry(myModel).State = EntityState.Modified;
DbContext.SaveChanges();
return RedirectToAction("Index");
}
return View(myModel);
}
DBContext
public class ModelContext : DbContext
{
public DbSet<MyModel> MyModelSet{ get; set; }
}
More info about DBContext.
With help of Slauma in the comments in the repost or extension of this question at:
Repost/Extension
This is what he suggested i do and it works.
Add to IDataSource Interface:
void Update(MensPlayer mensPlayer);
Update Implemented in Db class:
void IDataSource.Update(MensPlayer mensPlayer)
{
Entry(mensPlayer).State = EntityState.Modified;
}
Edit Action:
[HttpPost]
public ActionResult Edit(MensPlayer mensPlayer)
{
if (ModelState.IsValid)
{
//Save Player
_dataSource.Update(mensPlayer);
_dataSource.Save();
TempData["message"] = string.Format("{0} has been saved", mensPlayer.Name);
return RedirectToAction("Detail", "MensPlayer", new {id = mensPlayer.Id});
}
return View(mensPlayer);
}
And Just like that all works fine, although i was under the assumption that i would implement Update to the whole DbSet like i did with Save.

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.