I have successfully inserted data into two tables which are working fine. Now I am just stuck as to how I can get the details from both tables and update them. After inserting, I want to query both tables using an id and get the records, and then use the Id to update.
This is what I am looking for.
get data from two tables
update tables(pass id)
It must be an API that communicates with my classes because I want to display the data from the view
DB Models
1.
public class WholesaleRateSheetMarkup
{
[Key]
public int RateSheetMarkupId { get; set; }
[Required]
public int ResellerId { get; set; }
[StringLength(50)]
public string RatesheetName { get; set; }
}
2.
public class WholesaleRateSheet
{
[Key]
public int RateSheetId { get; set; }
[Required]
public int RateSheetMarkupId { get; set; }
public string CountryCode { get; set; }
public string Description { get; set; }
public decimal Peak { get; set; }
public bool IsSouthAfricanRate { get; set; }
public bool IsInertnationRate { get; set; }
public bool IsSpecificRate { get; set; }
public int DestinationGroupSetId { get; set; }
public int DestinationGroupId { get; set; }
public string DestinationLookup { get; set; }
public DateTime CreatedDate { get; set; }
public string CreatedByUsername { get; set; }
public DateTime LastUpdatedDate { get; set; }
public string UpdatedByUsername { get; set; }
}
My controller: This controller calls service class
[HttpPost]
[Route("[controller]/addRateSheet/{resellerId}/{productName}")]
public IActionResult AddRateSheet(int resellerId, string productName , int destinationGroupSetId, [FromBody]List<RateSheetSummary> rateSheetSummaries)
{
RateSheetService rateSheetService = new RateSheetService();
return Ok(rateSheetService.SaveRateSheet(resellerId, productName, rateSheetSummaries));
}
This is how I am saving to the database
public RateSheetModel SaveRateSheet(int resellerId, string productName, [FromBody]List<RateSheetSummary> rateSheetSummaries)
{
int latestId;
RateSheetModel rateSheetModel = new RateSheetModel();
try
{
#region Save rate sheet to the tabase
if (RateSheetObj != null)
{
#region WholesaleRateSheetMarkup
var wholesaleRateSheetMarkup = new WholesaleRateSheetMarkup
{
ResellerId = resellerId,
RatesheetName = productName,
};
_Context.WholesaleRateSheetMarkup.Add(wholesaleRateSheetMarkup);
_Context.SaveChanges();
//get latest RateSheetMarkupId
latestId = wholesaleRateSheetMarkup.RateSheetMarkupId;
#endregion
#region WholesaleRateSheet
#region commented out
List<WholesaleRateSheet> wholesaleRateSheets = new List<WholesaleRateSheet>();
foreach (var item in rateSheetSummaries)
{
wholesaleRateSheets.Add(new WholesaleRateSheet()
{
RateSheetMarkupId = latestId,
CountryCode = item.CountryCode,
Description = item.Description,
Peak = item.Peak,
IsSouthAfricanRate = item.IsSouthAfricanRate,
IsSpecificRate = item.IsSpecificRate,
DestinationGroupSetId = 1,
DestinationGroupId = 1,
DestinationLookup = item.DestinationLookup,
CreatedDate = DateTime.Now
}); ;
_Context.WholesaleRateSheet.AddRange(wholesaleRateSheets);
_Context.SaveChanges();
}
#endregion
}
}
}
}
Trying to fetch data from my tables. At this point, I don't know how to continue further as I want to get the details and so that I can bind the data from the view.
public RateSheetModel getRatesheetDetails(int rateSheetMarkupId)
{
RateSheetModel model = new RateSheetModel();
using (var context = new AppClientZoneContext())
{
var select = (from rsm in context.WholesaleRateSheetMarkup
join rs in context.WholesaleRateSheet
on rsm.RateSheetMarkupId equals rs.RateSheetMarkupId
where rsm.RateSheetMarkupId == rateSheetMarkupId
select new
{
rsm.RatesheetName,
rs.CountryCode,
rs.Description,
rs.Peak,
rs.IsSouthAfricanRate,
rs.IsInertnationRate,
rs.RateSheetMarkupId,
rs.IsSpecificRate,
rs.DestinationGroupSetId,
rs.DestinationGroupId,
rs.DestinationLookup,
rs.CreatedDate,
rs.CreatedByUsername,
rs.LastUpdatedDate,
rs.UpdatedByUsername,
}).FirstOrDefault();
}
return model;
}
Update API
[HttpPost]
[Route("[controller]/updateRateSheet/{resellerId}/{ratesheetId}")]
public IActionResult UpdateRateSheet(int resellerId, int ratesheetId, string productName)
{
RateSheetService UpdateRateSheetService = new RateSheetService();
return Ok(UpdateRateSheetService.UpdateRateSheet(resellerId,ratesheetId, productName));
}
Update function: I don't know how to best approach update functionality
public RateSheetModel UpdateRateSheet(int resellerId, int rateSheetId, string productName)
{
RateSheetModel mm = new RateSheetModel();
return mm;
}
Related
I am trying to bind a model in a post action method. i.e binding with the help of [Bind] attribute.
Where I post some fields for parent while a collection of child properties at the same time.
Supose I have parent as following
class Parent
{
int field0;
string field1;
string field2;
ICollection<Child> Children;
}
class Child
{
int field3;
string field4;
string field5;
}
at the time of binding I can choose fields to bind for simple binding like [Bind("field1, field2")] and to include children as well then [Bind("field1,field2,children")]
But I need to include some fields of children like children("field4", "field5")
Is there any possibility so that I can write like following
public IActionResult UTOneFlight([Bind("field1, field2, children(field4, field5)")] Parent p)
{
}
UPDATE
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> UTOneFlight([Bind("FlightID, SrcAirportID, DestAirportID, FlightDate, Sector, RegistrationNo, FlightNo, CallSign, CrewMembers, EmbDetails, UpdateRemarks")] FlightViewModel f)
{
if (f != null && f.EmbDetails != null)
{
if (f.FlightID == 0)
{
var flight = new Flight()
{
EmbDetails = new List<EmbDetail>(),
FlightType = "emb",
AirlineOperatorID = _user.OperatorID,
SrcAirportID = f.SrcAirportID,
DestAirportID = f.DestAirportID,
FlightDate = f.FlightDate,
Sector = f.Sector.ToString().ToLower()[0],
FlightNo = f.FlightNo.Trim().ToLower(),
CallSign = f.CallSign.Trim().ToLower(),
RegistrationNo = f.RegistrationNo.Trim().ToLower(),
CrewMembers = f.CrewMembers,
UpdateRemarks = f.UpdateRemarks?? f.UpdateRemarks,
EmbDataStatus = 'u',
CreatedBy = _user.UserID
};
foreach (var e in f.EmbDetails)
{
flight.EmbDetails.Add(
new EmbDetail()
{
PaxType = e.PaxType,
PaxClass = e.PaxClass,
AdultPax = e.AdultPax,
Infants = e.Infants,
Dips = e.Dips,
FOC = e.FOC,
TransferPax = e.TransferPax,
CreatedBy = _user.UserID
}
);
}
await _db.AddAsync(flight);
return RedirectToAction("Index");
}
else
{
//var flight = await _db.SingleAsync<Flight>(x => x.FlightID == f.FlightID);
//return RedirectToAction("Index");
}
}
else
return NotFound();
}
and my models are
public class FlightViewModel
{
public long FlightID { get; set; }
public int SrcAirportID { get; set; }
public int DestAirportID { get; set; }
public string RegistrationNo { get; set; }
public string FlightNo { get; set; }
public string CallSign { get; set; }
public DateTime FlightDate { get; set; }
public int CrewMembers { get; set; }
public char Sector { get; set; }
public string UpdateRemarks { get; set; }
public ICollection<EmbDetViewModel> EmbDetails { get; set; }
}
and
public class EmbDetViewModel
{
public string PaxType { get; set; }
public char PaxClass { get; set; }
public int AdultPax { get; set; }
public int Infants { get; set; }
public int Dips { get; set; }
public int Crew { get; set; }
public int FOC { get; set; }
public int TransferPax { get; set; }
}
I need to write signature of the method like
public async Task<IActionResult> UTOneFlight([Bind("FlightID, SrcAirportID, DestAirportID, FlightDate, Sector, RegistrationNo, FlightNo, CallSign, CrewMembers, EmbDetails(PaxType, PaxClass), UpdateRemarks")] FlightViewModel f)
Please have a look at
EmbDetails(PaxType, PaxClass)
How do you send your request body? I test in my side and here's the result.
My model:
public class ParentTestModel
{
public int id { get; set; }
public ICollection<TestModel> testModels { get; set; }
}
public class TestModel
{
public string prefix { get; set; }
}
==============================Update=============================
I test in my side with [JsonIgnore] and the property which added this annotation will be ignored and this is suitable when the request body is a json object like the screenshot above. And if you are sending the request in form-data then you can use [Bind] annotation, I think you may have referred to this document.
I have a post method in my controller that looks like this and I want AvailableSeats to reduce by 1 anytime I post the form. The problem is when I run the program for the very first time and post the form, everything works perfectly but for subsequent times, the database values for the AvailableSeats doesn't reduce by 1, it just remains constant and I can't figure out why.
[HttpPost]
public ActionResult Create(BookingViewModel viewModel)
{
if (viewModel.FromLocationId == viewModel.ToLocationId)
{
return RedirectToAction("Index");
}
var busFromDb = _context.Buses.First(c=>c.Id == viewModel.BusId);
var seatsFromDb = busFromDb.BusSeats;
var reduce = seatsFromDb - 1;
if (busFromDb != null)
{
var book = new Booking
{
AvailableSeats = reduce,
FromLocationId = viewModel.FromLocationId,
ToLocationId = viewModel.ToLocationId,
BusId = viewModel.BusId,
DateTime = viewModel.DateTime,
};
_context.Bookings.Add(book);
}
_context.SaveChanges();
return RedirectToAction("Index", "Home");
}
My Booking Class
public class Booking
{
[Required]
public int Id { get; set; }
public FromLocation FromLocation { get; set; }
public int FromLocationId { get; set; }
public ToLocation ToLocation { get; set; }
public int ToLocationId { get; set; }
public Bus Bus { get; set; }
[Required]
public int BusId { get; set; }
public DateTime DateTime { get; set; }
public int AvailableSeats { get; set; }
}
My Bus class
public class Bus
{
public int Id { get; set; }
public string BusNumber { get; set; }
public BusService BusService { get; set; }
public int BusSeats { get; set; }
}
As requested, this is my DbContext class
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public DbSet<Bus> Buses { get; set; }
public DbSet<Booking> Bookings { get; set; }
public DbSet<FromLocation> FromLocations { get; set; }
public DbSet<ToLocation> ToLocations { get; set; }
public ApplicationDbContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
}
After which I initialized it in my controller.
public class BookingsController : Controller
{
private ApplicationDbContext _context;
public BookingsController()
{
_context = new ApplicationDbContext();
}
Currently, you are deducting total bus seats by 1 (24 - 1) that always return 23 for each booking because you don't update the value 24 from Bus table, I am assuming which is total number of seats in a given bus. Rather you can count total bookings made for per bus that gives you the remaining seats.
int seatsFromDb = busFromDb.BusSeats; //24
int soldSeats = _context.Bookings.Count(b => b.BusId == viewModel.BusId); //2 (you need to add more filters)
int remainingSeats = seatsFromDb - (soldSeats + 1) //include the current booking (sold 3)
var book = new Booking
{
AvailableSeats = remainingSeats,
// ...
Hi I tried this code with same entitty structure and now result is that on every booking the bus table BusSeats reduce to one and in Booking table availabe seats reduce to one. I think this is want you wanted.
public ActionResult Index()
{
-- I hardcoded id because I donthave all view model but with this i was able to achieve the result you required.
int BusId = 1;
var _context = new TestContext();
var busFromDb = _context.Buses.FirstOrDefault(c => c.Id == BusId);
var seatsFromDb = busFromDb.BusSeats;
var reduce = seatsFromDb - 1;
if (busFromDb != null)
{
busFromDb.BusSeats = busFromDb.BusSeats - 1;
var book = new Booking
{
AvailableSeats = reduce,
BusId = BusId,
DateTime =DateTime.Now,
Bus = busFromDb
};
book.Bus = busFromDb;
_context.Entry(busFromDb).State = EntityState.Modified;
_context.Bookings.Add(book);
}
_context.SaveChanges();
return View();
}
Below is my EF classes
public class TestContext:DbContext
{
public TestContext()
: base("name=TestConnection")
{
}
public virtual DbSet<Bus> Buses { get; set; }
public virtual DbSet<Booking> Bookings { get; set; }
}
}
public class Booking
{
public int Id { get; set; }
public Bus Bus { get; set; }
public int BusId { get; set; }
public DateTime DateTime { get; set; }
public int AvailableSeats { get; set; }
}
public class Bus
{
public int Id { get; set; }
public string BusNumber { get; set; }
public int BusSeats { get; set; }
}
This a simple project where users can search for job postings by area of expertise. The relationship between Areas and Postings are Many-to-many. I seem to be able to get to the very last part of retrieving the correctly filtered list, but getting back into the view model keeps giving me different errors:
ViewModel:
public class AreaOfertasViewModel
{
public Oferta UnaOferta { get; set; }
public SelectList AreasTrabajo { get; set; }
public IEnumerable<Oferta> Ofertas { get; set; }
public int idArea { get; set; }
public AreaOfertasViewModel()
{
this.UnaOferta = UnaOferta;
this.Ofertas = new List<Oferta>();
cargarAreas();
}
private void cargarAreas()
{
PostulaOfertaContext db = new PostulaOfertaContext();
this.AreasTrabajo = new SelectList(db.Areas, "areaId", "Area");
}
}
}
Controller:
public ActionResult SearchXArea()
{
return View(new AreaOfertasViewModel());
}
[HttpPost]
public ActionResult SearchXArea(AreaOfertasViewModel aovm)
{
int id = aovm.idArea;
PostulaOfertaContext db = new PostulaOfertaContext();
var area = db.Areas.Where(c => c.areaId == id);
var ofertas = from c in db.Ofertas.Where(r => r.AreaTrabajo == area)
select c;
aovm.Ofertas = (IEnumerable<Oferta>)ofertas.ToList();
return View(aovm);
}
The line giving me issues is
aovm.Ofertas = (IEnumerable)ofertas.ToList();
I've tried List<> for Ofertas, and I've tried leaving it as .ToList() without casting, and casting it as different things, but it gives me errors about not being able to cast it, and "Cannot compare elements of type 'System.Collections.Generic.List`1'. Only primitive types, enumeration types and entity types are supported."
What's the solution here?
Model for AreaTrabajo:
public class AreaTrabajo
{
[Key]
public int areaId { get; set; }
public string Area { get; set; }
public virtual List<Oferta> oferta { get; set; }
}
Model for Oferta:
public class Oferta
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Required]
public string Titulo { get; set; }
[Required]
public DateTime Vencimiento { get; set; }
[Required]
public string Cargo { get; set; }
[Required]
public int HorarioComienzo { get; set; }
[Required]
public int HorarioFin { get; set; }
[Required]
public string DescripcionTareas { get; set; }
public int Remuneracion { get; set; }
[Required]
public int RangoEdadMin { get; set; }
[Required]
public int RangoEdadMax { get; set; }
public string TipoFormacion { get; set; }
public string Idiomas { get; set; }
public string Competencias { get; set; }
public string OtrosEstudios { get; set; }
public string Estado { get; set; }
public virtual List<AreaTrabajo> AreaTrabajo { get; set; }
public virtual TipoContrato TipoContrato { get; set; }
public virtual Empresa Empresa { get; set; }
public virtual List<Postulante> Postulantes { get; set; }
}
Answer
[HttpPost]
public ActionResult SearchXArea(AreaOfertasViewModel aovm)
{
int id = aovm.idArea;
PostulaOfertaContext db = new PostulaOfertaContext();
var area = db.Areas.Where(c => c.areaId == id).FirstOrDefault();
var ofertas = db.Ofertas.Where(s => s.AreaTrabajo.All(e => e.areaId == area.areaId)).ToList();
aovm.Ofertas = ofertas;
return View(aovm);
}
Sorry if my question wasn't clear enough. I needed to filter out from the many-to-many relationship, and this solved it.
You are getting an error because the actual sql is executed when you call tolist(). The error is in your sql because you are comparing AreaTrabago to a list.
[HttpPost]
public ActionResult SearchXArea(AreaOfertasViewModel aovm)
{
int id = aovm.idArea;
PostulaOfertaContext db = new PostulaOfertaContext();
var area = db.Areas.Where(c => c.areaId == id).FirstOrDefault();
var ofertas = db.Ofertas.Where(s => s.AreaTrabajo.All(e => e.areaId == area.areaId)).ToList();
aovm.Ofertas = ofertas;
return View(aovm);
}
Sorry if my question wasn't clear enough. I couldn't get the many-to-many relationship, and this solved the filtering problem perfectly.
I have been searching for days now trying to figure this one out. It saves my records correctly but throws the following error:
The changes to the database were committed successfully, but an error occurred while updating the object context. The ObjectContext might be in an inconsistent state. Inner exception message: Unable to set field/property Actors on entity type BOR.DataModel.StagComplaint. See InnerException for details.
I am using Code First and EF 5 in a C# Web Forms solution with a supporting WCF Service. Here are my POCO classes:
public partial class StagComplaint : ComplaintBase {
public IList<StagParcel> Parcels { get; set; }
public IList<StagActor> Actors { get; set; }
public IList<StagRectification> Rectifications { get; set; }
public ComplaintType ComplaintType { get; set; }
public int ComplaintTypeID { get; set; }
public StagComplaint() {
this.Parcels = new List<StagParcel>();
this.Actors = new List<StagActor>();
this.Rectifications = new List<StagRectification>();
}
}
public class ComplaintBase : BORBase {
public string Number { get; set; }
public int ParentID { get; set; }
public int TaxYear { get; set; }
public string Category { get; set; }
public double BuildingValue { get; set; }
public double LandValue { get; set; }
public double OwnerOpinion { get; set; }
public string Notes { get; set; }
}
public class BORBase {
[Required]
public DateTime CreationDate { get; set; }
public int ID { get; set; }
[MaxLength(25)]
[Required]
public string UserIdentification { get; set; }
}
public partial class StagParcel : ParcelBase {
public virtual StagActor Owner { get; set; }
[ForeignKey("Owner")]
public int OwnerID { get; set; }
public StagAddress Address { get; set; }
[IgnoreDataMember]
public virtual StagComplaint Complaint { get; set; }
public int ComplaintID { get; set; }
public StagParcel() {
this.Address = new StagAddress();
}
}
public class ParcelBase : BORBase {
public string Number { get; set; }
public double BuildingValue { get; set; }
public double LandValue { get; set; }
public double OwnerOpinion { get; set; }
public string LandUseCode { get; set; }
public string NeighborhoodCode { get; set; }
public string TaxDistrict { get; set; }
public string SchoolDistrict { get; set; }
public int SchoolBoardID { get; set; }
}
public partial class StagActor : ActorBase {
public StagAddress Address { get; set; }
public virtual IList<StagEmail> Emails { get; set; }
public virtual IList<StagPhone> Phones { get; set; }
[IgnoreDataMember]
public virtual StagComplaint Complaint { get; set; }
public int ComplaintID { get; set; }
public virtual Role Role { get; set; }
public int RoleID { get; set; }
public StagActor() {
this.Emails = new List<StagEmail>();
this.Phones = new List<StagPhone>();
this.Address = new StagAddress();
}
}
public class ActorBase : BORBase {
public string Name { get; set; }
}
public class StagRectification : BORBase {
public bool Active { get; set; }
public string Notes { get; set; }
public virtual RectificationType RectificationType { get; set; }
public int RectificationTypeID { get; set; }
[IgnoreDataMember]
public virtual StagComplaint Complaint { get; set; }
public int ComplaintID { get; set; }
}
This is the client side code I am using to create the Complaint:
public int AddParcelsToStagingComplaint(List<string> parcelIDs, string userID) {
StagComplaint comp = new StagComplaint();
int Result = 0;
using (BORServiceClient db = new BORServiceClient()) {
comp = new StagComplaint() {
BuildingValue = 111222,
Category = "*",
LandValue = 222333,
Number = "*",
TaxYear = DateTime.Now.Year,
ComplaintTypeID = 1,
UserIdentification = userID,
CreationDate = DateTime.Now,
};
StagAddress ca = new StagAddress() { Line1 = "670 Harvard Blvd", City = "Cleveland", State = "OH", ZipCode = "44113", };
List<StagPhone> ps = new List<StagPhone>();
ps.Add(new StagPhone() { Number = "5556664646", Type = PhoneTypes.Home, UserIdentification = userID, CreationDate = DateTime.Now, });
comp.Actors.Add(
new StagActor() {
Name = "Joe Schmoe",
Address = ca,
Phones = ps,
RoleID = 1,
UserIdentification = userID,
CreationDate = DateTime.Now,
}
);
StagAddress aa = new StagAddress() {
City = wp.Address.City,
Line1 = wp.Address.Line1,
Line2 = wp.Address.Line2,
State = wp.Address.State,
ZipCode = wp.Address.ZipCode,
};
ps = new List<StagPhone>();
ps.Add(new StagPhone() { Number = "4448887878", Type = PhoneTypes.Work, UserIdentification = userID, CreationDate = DateTime.Now, });
StagParcel p = new StagParcel() {
Address = new StagAddress() { Line1 = "4 Oxford Drive", City = "Hudson", State = "OH", ZipCode = "44236" },
BuildingValue = wp.BuildingValue,
LandUseCode = wp.LandUseCode,
LandValue = wp.LandValue,
NeighborhoodCode = wp.NeighborhoodCode,
Number = wp.Number,
Owner = new StagActor() { Name = "Owner Person", Address = aa, RoleID = 2, Phones = ps, UserIdentification = userID, CreationDate = DateTime.Now, },
OwnerOpinion = wp.OwnerOpinion,
SchoolBoardID = wp.SchoolBoardID,
SchoolDistrict = wp.SchoolDistrict,
TaxDistrict = wp.TaxDistrict,
UserIdentification = userID,
CreationDate = DateTime.Now,
};
comp.Parcels.Add(p);
ServiceResponse<int> saved = db.AddComplaint((ComplaintBase)comp, Contexts.Staging, userID);
if (saved.WasSuccessful)
Result = saved.Result;
} // using the database
return Result;
} // AddParcelsToStagingComplaint - Method
Here is the WCF method that gets called:
using (StagComplaintRepo cr = new StagComplaintRepo()) {
cr.Add((StagComplaint)complaint, userID);
if (cr.Save()) {
Result.Result = complaint.ID;
Result.WasSuccessful = true;
} else {
Result.AddException(string.Format("Unable to create a new Complaint in the {0} context.", context));
} // if the save was successful
} // using the Complaint Repository
And here is the BaseRepository that has the Save and Add methods:
public abstract class BaseRepository<T> : IDisposable, IRepository<T> where T : class {
public virtual bool Save(bool detectChanges = false) {
if (detectChanges == true)
this.Entities.ChangeTracker.DetectChanges();
return (this.Entities.SaveChanges() > 0);
}
public virtual void Add(T entity, string userID) {
this.Entities.Set<T>().Add(entity);
}
...
}
It fails on the above this.Entities.SaveChanges() call with the error mentioned at the top of this post. There is no extra inner exception. If I only fill in the Complaint properties that are required and are part of that object, it works. But once I add a Parcel with an Actor it fails.
I assume it is something simple, perhaps a switch needs to be turned on or off. But similar errors all seem to reference AcceptChanges and that is not the issue here. At least based on the error message. Any help would be appreciated.
EDIT
Here is the full stack trace:
at System.Data.Objects.ObjectContext.SaveChanges(SaveOptions options)
at System.Data.Entity.Internal.InternalContext.SaveChanges()
at System.Data.Entity.Internal.LazyInternalContext.SaveChanges()
at System.Data.Entity.DbContext.SaveChanges()
at BOR.WebService.Repositories.BaseRepository`1.Save(Boolean detectChanges) in d:\DevProjects\BOR\WebService\Main\Source\WebServiceSolution\WcfServiceProject\Repositories\BaseRepository.cs:line 22
at BOR.WebService.BORService.AddComplaint(ComplaintBase complaint, Contexts context, String userID) in d:\DevProjects\BOR\WebService\Main\Source\WebServiceSolution\WcfServiceProject\BORService.svc.cs:line 65
Line 22 is:
return (this.Entities.SaveChanges() > 0);
Line 65 is:
if (cr.Save()) {
I'm using EF4.1 code first to create a simple database app with SQL CE 4 backend. I have a Product class and a CallItem class defined as so:
class CallItem
{
public int id { get; set; }
public float discount { get; set; }
public virtual Product Product { get; set; }
}
class Product
{
public int id { get; set; }
public decimal BaseCost { get; set; }
public int UnitSize { get; set; }
public bool isWasteOil { get; set; }
public string Code { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Ingredients { get; set; }
}
edit - When I am creating a collection of CallItems using a LINQ query, I cannot access the attributes of the Product attached to each CallItem, eg
var callItems = from ci in context.CallItems select ci;
foreach(CallItem callItem in callItems)
{
RunSheet nrs = new RunSheet();
nrs.prodCode = callitem.Product.Code;
}
Interrogating the database shows that Productid in CallItems is being populated. However, the following line generates a NullReferenceException during run time:
nrs.prodCode = callitem.Product.Code;
Because callitem.Product is evaluating to null. Is this something to do with lazy loading and if so how can I resolve the issue?
RunSheet is another class, nrs is an instance whose attribute 'prodCode' I want to populate with the CallItem's Product's code.
Thanks!
From that code what you've showed it should work. Have you tried explicit loading?
var callItems = from ci in context.CallItems.Include(c => c.Product) select ci;
foreach(CallItem callItem in callItems)
{
RunSheet nrs = new RunSheet();
nrs.prodCode = callitem.Product.Code;
}
public class CallItem
{
public int Id { get; set; }
public float Discount { get; set; }
public virtual Product Product { get; set; }
}
public class Product
{
public int Id { get; set; }
public decimal BaseCost { get; set; }
public int UnitSize { get; set; }
public bool IsWasteOil { get; set; }
public string Code { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Ingredients { get; set; }
}
using (var context = new StackOverFlowContext())
{
var p = new Product
{
Id = 1,
BaseCost = 200,
Code = "Hola",
Description = "Soe description",
Ingredients = "Some ingredients",
IsWasteOil = true,
Name = "My Product",
UnitSize = 10
};
var item = new CallItem
{
Id = 101,
Discount = 10,
Product = p
};
context.CallItems.Add(item);
context.SaveChanges();
var result = from temp in context.CallItems
select temp;
Console.WriteLine("CallItem Id"+result.First().Id);
Console.WriteLine("ProductId"+result.First().Product.Id);
}
I wrote the above code with the following output
CallItemId 1
ProductId 1
The sql Profiler showed this
SELECT TOP (1)
[c].[Id] AS [Id],
[c].[Discount] AS [Discount],
[c].[Product_Id] AS [Product_Id]
FROM [dbo].[CallItems] AS [c]
It was too long for a comment ,so i put it here .