"Sequence contains no elements" error in Entity Framework - c#

When I try to retrieve an object from a local database, it throws an exception
Sequence contains no elements
However I have added sample data into database. What can cause this error?
private void BindObjectToControls()
{
Item = new Item();
//set values entered by user into UI to corresponding properties of the object
try
{
Item.Description = cbxType.Text.ToString() + ", " + tbxDesc.Text;
Item.Category = (string)cbxCategory.SelectedItem;
Item.Brand = (string)cbxBrand.SelectedItem;
Item.Price = (int)nudPrice.Value;
}
catch(NullReferenceException ex)
{
MessageBox.Show("Error" + ex);
}
}
private void Save()
{
BindObjectToControls();
ComputerUZEntities db = new ComputerUZEntities();
if (isNew)
{
db.Items.Add(Item);
}
else
{
Item myItem = (from ctx in db.Items where ctx.ItemID == Item.ItemID select ctx).Single();
//Item is global variable.
myItem.Description = Item.Description;
myItem.Category = Item.Category;
myItem.Brand = Item.Brand;
myItem.Price = Item.Price;
}
db.Items.SqlQuery(sql);
db.SaveChanges();
MessageBox.Show("Saved!");
this.Close();
}
P.S I have tried all 4 calls Single, SingleOrDefault, First, FirstOrDefault. None of them has worked.

Well the problem is not with those 4 calls. The problem is that you are creating new object everytime when BindObjectToControls() method is called. Instead of creating a new Item() inside of BindObjectToControls(), Try to make inside constructor or somewhere else.

Related

Getting double data in DB

I pull student data from 2 databases. 1 from an online SOAP API which can handle async calls and 1 from a local DB with an older services that doesnt support async.
I compare these databases and write the differences in a local sqlDB through EF.
Problem:
I get double entries in my EF DB. He puts the correct data and amount in arrays inside the method, but it looks like once he hits the db.savechanges() he jumps back up a few line and saves again.
I don't even know where this extra thread comes from.
Some code might be still there from numerous tries to solve it. For instance I tried with addrange but I get an error when he tries to add the FullVarianceList.
public async Task<bool> FullStudentCompare(string date) //format DD/MM/YYYY
{
try
{
//DB context
using (var db = new SchoolDbContext())
{
//GET DATA
//SMT (async)
List<SmtStudent> smtStdudentList = await GetAllSmartschoolStudents();
//Wisa (sync)
//on date, or if emty on current systemdate
List<WisaStudent> wisaList;
if (date == "")
{
wisaList = GetWisaStudentData(DateTime.Now.ToShortDateString());
}
else
{
wisaList = GetWisaStudentData(date);
}
//Flags and props needed for DB entry after compare
bool existsInLocalDb = false;
List<Variance> vList = new List<Variance>();
//Full list to add to DB outside foreach
List<Variance> fullVarianceList = new List<Variance>();
//Full List of new Students to write to DB outside foreach
List<DbStudent> fullStudentList = new List<DbStudent>();
//Compare lists
foreach (WisaStudent wstd in wisaList)
{
//determine correct classCode
string klasCode;
if (wstd.klasgroep.Trim() == "Klasgroep 00")
{
klasCode = wstd.klas.Trim();
}
else
{
klasCode = wstd.klasgroep.Trim();
}
//Create SmtStudent object for compare
SmtStudent tempStd = new SmtStudent(true,
wstd.voornaam.Trim(),
wstd.naam.Trim(),
wstd.stamboeknummer.Trim(),
wstd.geslacht.Trim(),
wstd.geboortedatum.Trim(),
wstd.straat.Trim(),
wstd.huisnummer.Trim(),
wstd.busnummer.Trim(),
wstd.postcode.Trim(),
wstd.gemeente.Trim(),
wstd.emailadres.Trim(),
wstd.GSM_nummer.Trim(),
wstd.levensbeschouwing.Trim(),
wstd.coaccountmoedervoornaam.Trim(),
wstd.coaccountmoedernaam.Trim(),
wstd.coaccountmoederemailadres.Trim(),
wstd.coaccountmoederGSM_nummer.Trim(),
wstd.coaccountvadervoornaam.Trim(),
wstd.coaccountvadernaam.Trim(),
wstd.coaccountvaderemailadres.Trim(),
wstd.coaccountvaderGSM_nummer.Trim(),
klasCode,
wstd.nationaliteit,
wstd.geboorteGemeente,
wstd.geboorteLand
);
//Find matching SmtStudent
SmtStudent smtStd = smtStdudentList.Find(i => i.Internnummer == wstd.stamboeknummer);
//Find matching Std in local DB
DbStudent dbStd = await db.Students.Where(i => i.Stamboeknummer == wstd.stamboeknummer).FirstOrDefaultAsync();
//if none exists in the local DB create an entity to update and write to DB
if (dbStd == null)
{
dbStd = new DbStudent(wstd.voornaam.Trim(),
wstd.naam.Trim(),
wstd.stamboeknummer.Trim(),
wstd.geslacht.Trim(),
wstd.geboortedatum.Trim(),
wstd.straat.Trim(),
wstd.huisnummer.Trim(),
wstd.busnummer.Trim(),
wstd.postcode.Trim(),
wstd.gemeente.Trim(),
wstd.emailadres.Trim(),
wstd.GSM_nummer.Trim(),
wstd.levensbeschouwing.Trim(),
wstd.coaccountmoedervoornaam.Trim(),
wstd.coaccountmoedernaam.Trim(),
wstd.coaccountmoederemailadres.Trim(),
wstd.coaccountmoederGSM_nummer.Trim(),
wstd.coaccountvadervoornaam.Trim(),
wstd.coaccountvadernaam.Trim(),
wstd.coaccountvaderemailadres.Trim(),
wstd.coaccountvaderGSM_nummer.Trim(),
klasCode,
wstd.loopbaanDatum,
wstd.nationaliteit,
wstd.geboorteGemeente,
wstd.geboorteLand
);
db.Students.Add(dbStd);
fullStudentList.Add(dbStd);
}
else
{
existsInLocalDb = true;
}
if (smtStd == null)
{
//Std doesn't exist in Smt -> New student
dbStd.IsNewStudent = true;
dbStd.ClassMovement = true;
//remove from wisaList
wisaList.Remove(wstd);
}
else
{
//clear vlist from previous iterations
vList.Clear();
//get all properties on the obj, cycle through them and find differences
PropertyInfo[] props = smtStd.GetType().GetProperties();
vList.AddRange(props.Select(f => new Variance
{
Property = f.Name,
ValueA = f.GetValue(smtStd),
ValueB = f.GetValue(tempStd),
Checked = false
})
.Where(v => !v.ValueA.Equals(v.ValueB) && v.ValueB != null)
.ToList());
//If the users allrdy exists in LocalDb delete all previously recorded variances
if (existsInLocalDb)
{
if (db.Variances.Where(j => j.Student.StudentId.Equals(dbStd.StudentId)).FirstOrDefault() != null)
{ //if the student allready exists we will recreate the variancelist, hence deleting all current items first
List<Variance> existingList = db.Variances.Where(j => j.Student.StudentId.Equals(dbStd.StudentId)).ToList();
foreach (Variance v in existingList)
{
db.Variances.Remove(v);
}
}
}
//Add new variances if vList is not empty
if (vList.Count > 0)
{
//Check if KlasCode is a variance -> set classmovement to true
if (vList.Where(i => i.Property == "KlasCode").FirstOrDefault() != null)
{
dbStd.ClassMovement = true;
}
else
{
dbStd.ClassMovement = false;
}
//add the StudentObject to the variance to link them 1-many
foreach (Variance v in vList)
{
v.Student = dbStd;
fullVarianceList.Add(v);
db.Variances.Add(v);
}
}
}
}
//add the full lists of variances and new students to DB
//db.Variances.AddRange(fullVarianceList);
//db.Students.AddRange(fullStudentList);
db.SaveChanges();
return true;
}
}
catch(Exception ex)
{
return false;
}
}
A couple of things:
It is important to understand that EF uses a unit of work pattern where none of the changes to the entities are persisted until SaveChanges is called which explains the "once he hits the db.Savechanges() he jumps back up" phenomenon.
When you have a 1 to many relationsship and you assign a collection of entities to a navigation property on another entity and then add that parent entity to the DbContext, EF marks those child entities to be added too. In your case dbStd is added at the line "db.Students.Add(dbStd);" and at the line "v.Student = dbStd;". This is most likely what is causing your duplicates.

EF Updating entity related table is inserting instead of updating

I have an object I am trying to update using Entity Framework 5.
Once I retrieve the existing object and go to update the fields, it correctly updates the base object "coach", but fails to update the Address object and instead inserts it again instead of updating it with a new primary key even though it has been passed the existing primary key to use again.
Any help is appreciated.
Below is a dumbed down version of the code:
using (AltairEntities context = new AltairEntities())
{
dtlCoach coach = context.dtlCoaches.FirstOrDefault(x => x.CoachID == coachId);
coach.Name = "Bob";
coach.Description = "sample";
coach.dtlCoachAddresses.Add(PrepareAddress(coach.dtlCoachAddresses.First().CoachAddressID));
context.Database.Connection.Open();
context.Entry(coach).State = EntityState.Modified;
context.SaveChanges();
}
public static dtlCoachAddress PrepareAddress(int existingId)
{
dtlCoachAddress newAddress = new dtlCoachAddress();
try
{
newAddress.CoachAddressID = existingId;
newAddress.AddressLine1 = "Line 1";
newAddress.AddressLine2 = "Line 2";
return newAddress;
}
catch (Exception ex)
{
throw ex;
}
}
UPDATE:
So I have found if I feed the existing dtlCoachAddress entity from inside the dtlCoach entity into the PrepareAddress function as a parameter instead of declaring the object as new, it updates correctly.
What is the difference between the dtlCoachAddress object from the entity and the dtlCoachAddress object defined from new, if I pass it all the same parameters? But the two define if the object gets inserted or updated?
I am not sure how you have arranged PKs and FKs in your entities. So this solution has a few assumptions.
Updating again to match OPs methods.
using (AltairEntities context = new AltairEntities())
{
dtlCoach coach = context.dtlCoaches.FirstOrDefault(x => x.CoachID == coachId);
coach.Name = "Bob";
coach.Description = "sample";
//coach.dtlCoachAddresses.Add(PrepareAddress(coach.dtlCoachAddresses.First().CoachAddressID));
//context.Database.Connection.Open();
//context.Entry(coach).State = EntityState.Modified;
var address = context.dtlCoachAddresses.FirstOrDefault(a => a.CoachAddressID == coachId);
if(address != null)
{
address.AddressLine1 = "Line 1";
address.AddressLine2 = "Line 2";
}
context.SaveChanges();
}
/*This function is not required
public static dtlCoachAddress PrepareAddress(int existingId)
{
using (AltairEntities context = new AltairEntities())
{
var address = context.dtlCoachAddresses.FirstOrDefault(a => a.CoachAddressID == coachId);
if(address != null)
{
address.AddressLine1 = "Line 1";
address.AddressLine2 = "Line 2";
context.SaveChanges();//update an existing address.
}
}
catch (Exception ex)
{
throw ex;
}
}*/

cannot be attached to this EntityContainer because it is already attached to another EntityContainer. Lightswitch Update a collection automatically

partial void updateRecords_Execute()
{
// Write your code here.
using (var tempWorkspace = new DataWorkspace())
{
Saving NewSavings = tempWorkspace.ApplicationData.Savings.AddNew();
var koo = from a in FromMainCompanies
select a;
foreach (var i in koo)
{
if (i.Member != null)
{
NewSavings.CaptureDate = DateTime.Now;
NewSavings.Amount = i.Member.Savings.Select(a => a.Amount).FirstOrDefault();
NewSavings.FinancialYear = tempWorkspace.ApplicationData.FinancialYears.FirstOrDefault();
NewSavings.Member = i.Member;
NewSavings.NewSavingsAmount = i.Member.Savings.Select(a => a.NewSavingsAmount).FirstOrDefault();
try
{
tempWorkspace.ApplicationData.SaveChanges();
}
catch (Exception e)
{
this.ShowMessageBox(e.Message);
}
}
}
}
}
Am trying to update records automatically in Lightswitch and I am getting the following error:
Entity 'Member : 6' cannot be attached to this EntityContainer because it is already attached to another EntityContainer.
I have the following tables, Member(s), Reconcilliation(s), FromMainCompany, ToMainCompany & Saving(s). Member is related to Savings i.e. A member has savings. And Member is also related FromMainCompany (FromMainCompany is a collection of Members and their total salary account deduction - NOT that important)
I have a button in my Reconcilliation screen called UpdateRecords (which has the code above on its Execute() method) that I want when clicked to add Member monthly savings automatically to all the Members Saving table but now I get this error - Entity 'Member : 6' cannot be attached to this EntityContainer because it is already attached to another EntityContainer.
-Thanks.
partial void updateRecords_Execute()
{
// Write your code here.
using (var tempWorkspace = new DataWorkspace())
{
var mymembers = tempWorkspace.ApplicationData.Members;
//var myscreen = this.Reconcilliations1.SelectedItem.FromMainCompanies.Where(a => a.Member != null).Select(b => b.Member);
//Member myMember = new Member();
foreach (Member item in mymembers)
{
Saving NewSavings = tempWorkspace.ApplicationData.Savings.AddNew();
////var koo = from a in FromMainCompanies
//// select a.Member;
NewSavings.CaptureDate = DateTime.Now;
NewSavings.Amount = item.Savings.Select(a=>a.Amount).LastOrDefault();
NewSavings.FinancialYear = tempWorkspace.ApplicationData.FinancialYears.FirstOrDefault();
NewSavings.Member = item;
NewSavings.NewSavingsAmount = item.Savings.Select(a=>a.NewSavingsAmount).LastOrDefault();
}
try
{
tempWorkspace.ApplicationData.SaveChanges();
}
catch (Exception e)
{
this.ShowMessageBox(e.Message);
}
}
}
Figured it out, the AddNew() was supposed to be in the foreach loop. - cheers

How to add a number of records into a List<T>

I have created an asp.net application using Entity Framework. In this I want to add the records into a list. For this I have to use the foreach loop but it always adding only last record data for all records, meaning it's showing same data. Here I have pasted my code. Please verify it once and guide where I can change.
public List<CategoryItems> ListMenuCategory(int MenuId)
{
string str = string.Empty;
string strJSON = string.Empty;
List<CategoryItems> resultmenu;
resultmenu = new List<CategoryItems>();
List<CategoryItems> Result;
Result = new List<CategoryItems>();
bool check = true;
var objmenuCategory = from cat in objEntity.menucategories where cat.MenuId == MenuId && cat.Active == check select cat;
CategoryItems Categorylist = new CategoryItems();
foreach (menucategory category in objmenuCategory)
{
Categorylist.CategoryName = category.CategoryName;
Categorylist.Description = category.Description;
int menuid = category.MenuCategoryId;
List<menuitem> menuitems = GetMenucategories(menuid);
foreach (var items in menuitems)
{
Categorylist.ItemName = items.ItemName;
Categorylist.Description = items.Description;
Categorylist.Price = (float)items.Price;
string Image = items.Picture;
Categorylist.Picture = "http://restaurantmanager.testshell.net/Images/" + Image;
Categorylist.Thumbnail = "http://restaurantmanager.testshell.net/Images/" + items.Thumbnail;
if (items.CreatedDate != null)
{
Categorylist.CreatedDate = (DateTime)items.CreatedDate;
}
if (items.ModifiedDate != null)
{
Categorylist.ModifiedDate = (DateTime)items.ModifiedDate;
}
Result.Add(Categorylist);
}
// Result.AddRange(menus);
}
return Result;
}
private List<menuitem> GetMenucategories(int p)
{
restaurantEntities objEntity1 = new restaurantEntities();
var menuitems = from items in objEntity1.menuitems where items.MenuCategoryId == p select items;
return menuitems.ToList();
}
You are creating the Categorylist item outside of the loops, so you are only using one single item, filling it with different data and adding it over and over to the result.
You have to create the item inside the innermost loop, so that each iteration gets its own object.
Note: ChrisF also spotted that you call AddRange inside the loop, which has the result that you will add the same set of items over and over. You don't need to call AddRange at all, you can just skip the Result list entirely and just return resultmenu instead.

WCF Data Service Query seems to be retrurning duplcate rows on repeated queries

I have a data class that return some objects from a wcf dataservice to a silverlight app:
void ExecuteWipReportQuery(DataServiceQuery qry)
{
context = new StaffKpiServices.HwfStaffKpiEntities(theServiceRoot);
qry.BeginExecute(new AsyncCallback(a =>
{
try
{
IEnumerable results = qry.EndExecute(a);
OnDataLoadingComplete(new WipReportByMonthEventArgs(results));
}
catch (Exception ex)
{
OnDataLoadingError(ex);
}
}), null);
}
The view model then get these results and adds them to an observable collection:
void wipReportDataContainer_DataLoadingComplete(object sender, Domain.WipReportByMonthEventArgs e)
{
Application.Current.RootVisual.Dispatcher.BeginInvoke(() =>
{
this.wipReport.Clear();
string s = "";
foreach (StaffKpiServices.WipReportByMonth r in e.Results)
{
//this.wipReport.Add(r);
//s += r.ClientCode;
this.wipReport.Add(new StaffKpiServices.WipReportByMonth
{
ClientCode = r.ClientCode,
ClientGroup = r.ClientGroup,
ClientName = r.ClientName,
ClientType = r.ClientType,
FinancialYear = r.FinancialYear,
Month = r.Month,
OSDebt = r.OSDebt,
OSDisb = r.OSDisb,
OSOther = r.OSOther,
OSTime = r.OSTime,
OSTotal = r.OSTotal,
PartnerUserName = r.PartnerUserName,
PracName = r.PracName,
Recov = r.Recov,
RecovFees = r.RecovFees,
RecPerc = r.RecPerc,
SicCode = r.SicCode,
SicParentName = r.SicParentName,
StaffName = r.StaffName,
YTDFees = r.YTDFees,
YTDTime = r.YTDTime
});
s += r.ClientCode + " ";
}
string s2 = "";
foreach (var p in this.wipReport)
{
s2 += p.ClientCode + " ";
}
OnPropertyChanged("WipReport");
if (null != LoadComplete)
{
LoadComplete(this, EventArgs.Empty);
}
});
}
Everything works ok, but if the data is refreshed two or three times, then the collections retrun contains the right number of objects, but all with duplicate properties. There seems to be no reason why, it is as if the foreach is not working on the collection, but at the same time not returning any errors. Any ideas?
Ok so this was odd.. but by recreating the object that fetches the data (the one that creates the context), all was ok, but if the viewmodel kept alive the object responsible for running the dataservice query, the problem occured.....
I have no idea why this should have been, but the problem has gone away.....

Categories