MVC4 Entity Framework Controller Database Issue - entity-framework

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.

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

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.

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

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

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.