I get this error whenever i try to update one of my models. The update is pretty simple:
Todo bn = service.GetTodos().Single(t => t.todoId == 1);
bn.Note.noteTitle = "Something new";
service.SaveTodo(bn);
And the models have this kind of structure:
A Todo has a Note
A Todo has a list of Tasks
I have my service's SaveTodo look a little something like this:
public void SaveTodo ( TodoWrapper note )
{
using (Repository repo = new Repository(new HpstrDataContext()))
{
if (note != null)
{
Todo todo = repo.Todos.SingleOrDefault(t => t.todoId == note.todoId);
if (todo == null)
{
todo = new Todo();
todo.Note = new Note();
}
todo.dueDate = note.dueDate;
todo.priority = (short)note.priority;
todo.Note.isTrashed = note.Note.isTrashed;
todo.Note.permission = (short)note.Note.permission;
todo.Note.noteTitle = note.Note.noteTitle;
repo.SaveTodo(todo);
}
}
}
And the Repository's SaveTodo method is pretty simple and looks like this:
public void SaveTodo ( Todo todo )
{
if (todo.Note.noteId == 0)
{
dc.NoteTable.InsertOnSubmit(todo.Note);
} else
{
dc.NoteTable.Attach(todo.Note);
dc.NoteTable.Context.Refresh(RefreshMode.KeepCurrentValues , todo.Note);
}
if (todo.todoId == 0)
{
dc.TodoTable.InsertOnSubmit(todo);
} else
{
dc.TodoTable.Attach(todo);
dc.TodoTable.Context.Refresh(RefreshMode.KeepCurrentValues , todo);
}
dc.SubmitChanges();
}
The error is being thrown at this line in the Repository: dc.NoteTable.Attach(todo.Note);. I've tried a lot of different things to get this to work but nothing seems to work.
Any help would be greatly appreciated
So i solved the problem (hopefully). In my Repository, i changed the SaveTodo to look like this
public void SaveTodo ( TodoWrapper note )
{
using (Repository repo = new Repository(new HpstrDataContext()))
{
if (note != null)
{
Todo todo = repo.Todos.SingleOrDefault(t => t.todoId == note.todoId);
if (todo == null)
{
todo = new Todo();
todo.Note = new Note();
}
todo.dueDate = note.dueDate;
todo.priority = (short)note.priority;
todo.Note.isTrashed = note.Note.isTrashed;
todo.Note.permission = (short)note.Note.permission;
todo.Note.noteTitle = note.Note.noteTitle;
foreach (TaskWrapper item in note.Tasks)
{
Task t = repo.Tasks.SingleOrDefault(task => task.tasksId == item.taskId);
if (t == null)
{
t = new Task();
}
t.Todo = todo;
t.isCompleted = item.isCompleted;
t.content = item.content;
repo.SaveTask(t);
}
}
}
}
If anybody was wondering, the wrappers are used as wrappers (no way) for the entities with wcf.
And my save task looked like this:
public void SaveTask ( Task task )
{
if (task.tasksId == 0)
{
dc.TaskTable.InsertOnSubmit(task);
} else
{
dc.TaskTable.Context.Refresh(RefreshMode.KeepCurrentValues , task);
}
dc.SubmitChanges();
}
I got rid of the Attach because I already pull out the Todo when calling the single or default statement so it was already attached to the database. So the error was correct because this entity was already attached to the database.
If i had made a new Todo instead of grabbing the one out the database, the attach would have worked. Hope this helps out anyone who stumbles upon this
Related
I set a background task on my application using hangfire. But the problem is on the local machine it works fine and the database changes work as well. On the web server, it also executes but can't make any changes to the database.
Here's the initiation code -
public IActionResult CornJobs()
{
CornExpression? corn = _context.Set<CornExpression>().AsNoTracking().FirstOrDefault();
if(corn.PayExpres == null)
{
RecurringJob.RemoveIfExists("Increase Payment");
}
else
{
RecurringJob.AddOrUpdate("Increase Payment", () => _students.IncreasePayment(), corn.PayExpres);
}
if (corn.SMSExpres == null)
{
RecurringJob.RemoveIfExists("Send Alert");
}
else
{
RecurringJob.AddOrUpdate("Send Alert", () => _students.SendDueAlert(), corn.SMSExpres);
}
return View(corn);
}
And here is the interface implementation
public bool IncreasePayment()
{
try
{
var students = _context.Set<Student>().AsNoTracking().Where(x => x.Status == 1 && (x.Batch1 == 1 || x.Batch2 == 1)).ToList();
foreach (var student in students)
{
if(GetMonthDifference(student.DateOfReg, DateTime.Now) == 0)
{
continue;
}
Due due = new()
{
StudentId = student.StudentId,
Recurring = DateTime.Now.ToString("MMMM, yyyy"),
Amount = student.Payment,
PreviousAmount = student.Due,
CurrentAmount = student.Due + student.Payment,
RecurredOn = DateTime.Now
};
student.TotalPayment += due.Amount;
student.Due += due.Amount;
_context.Update(student);
_context.Add(due);
}
_context.SaveChanges();
return true;
}
catch (Exception)
{
return false;
}
}
What mistake have I made here?
Thank you.
This question has been asked before in different forms, but none answer my question. I have scraped this forum and Windows dev forum for info, before posting this. I cannot make sense of how to accomplish this task.
I am at my wits end.
I have a DataGrid that is binded to an ICollectionView. This data was pulled via a stored procedure and the DataGrid is automatically generated based on the columns in each table. For reference, the SP returns a list of objects, each with a series of members like stock_symbol, stock_price, Date etc.
There are a series of filters I would like to apply to this collection view. Two comboboxes and two datepickers, to be more specific. Each with a checkbox to signify they are active.
Each checkbox event handler stores the data that was selected from the combobox or the datepicker. I am trying to compare what is in those variables, to each relevant member of the object list and send that filtered object list back to the DataGrid.
This is my code:
private void FillDataGrid()
{
//Connect contains a simple stored procedure connection to SQL server
var Client = Connect();
DTOClass[] dTOs = Client.GetData();
SetDTOClass(dTOs);
MainGrid.ItemsSource = FilterView(dTOs);
}
Here is FilterView() (apologies for the long commented sections, I am trying to include my attempts in one foul sweep):
public ICollectionView /*List<DTOClass>*/ FilterView(DTOClass[] DTO)
{
if (_CollectionViewInternal == null)
{
//Assign collected DTO object to an ICollectionView
_CollectionViewInternal =
CollectionViewSource.GetDefaultView(DTO);
}
/*
ObservableCollection<DTOClass> DTOview = null;
if (DTOViewInternal == null)
{
int j = DTO.Length;
DTOview = new ObservableCollection<DTOClass>();
for(int i = 0; i < j; i++)
{
DTOview.Add(DTO[i]);
}
DTOViewInternal = DTOview;
}
*/
//Add a default sort description to the Date column
_CollectionViewInternal.SortDescriptions.Add(new SortDescription("Date", ListSortDirection.Ascending));
//assign our view to the maingrid (move this to later in the
//MainGrid.ItemsSource = _CollectionViewInternal;
if (MainGrid.ItemsSource != null)
{
/*List<Predicate<IEnumerable<DTOClass[]>>>*/ FilteredView = new List<Predicate<IEnumerable<DTOClass[]>>>();
//DateTime _zeroDay = new DateTime(1, 1, 1);
//DateTime _now = DateTime.Now;
FilteredView.Clear();
return FilteredView = _CollectionViewInternal.Where(Function(w) w.accountname.Contains(txtFilter.Text) _
Or w.firstname.Contains(txtFilter.Text) _
Or w.lastname.Contains(txtFilter.Text) _
Or w.isenabled.Contains(txtFilter.Text) _
Or w.description.Contains(txtFilter.Text) _
Or w.lastlogontimestamp.Contains(txtFilter.Text) _
Or w.whencreated.Contains(txtFilter.Text) _
Or w.whenchanged.Contains(txtFilter.Text) _
Or w.oulocation.Contains(txtFilter.Text) _
Or w.co.Contains(txtFilter.Text) _
Or w.l.Contains(txtFilter.Text) _
Or w.state.Contains(txtFilter.Text))
//if (yearsChosen > 0)
/* Stock, Maxadj, FromDate, ToDate */
/*
if (Stock_CheckBox.IsChecked != null)
{
FilteredView.Add(new Predicate<IEnumerable<DTOClass[]>>(x => x.Where(item => item. == Stock_ComboBoxText)));
}
if (letterChosen != "Any")
{
FilteredView.Add(new Predicate<IEnumerable<DTOClass[]>>(x => x.LastName.StartsWith(letterChosen)));
}
if (genderChosen != "Any")
{
FilteredView.Add(new Predicate<IEnumerable<DTOClass[]>>(x => x.Gender.Equals(genderChosen.Substring(0, 1))));
}
_CollectionViewInternal.Filter = dynamic_Filter;
RaisePropertyChanged("PeopleView");
// Bring the current person back into view in case it moved
if (CurrentPerson != null)
{
IEnumerable<DTOClass[]> current = CurrentPerson;
_CollectionViewInternal.MoveCurrentToFirst();
_CollectionViewInternal.MoveCurrentTo(current);
}
*/
/*
if (DTOview == null)
{
DTOview = DTOViewInternal;
} else
{
DTOViewInternal.
}
*/
//var collection = DTO;
//var symbol = collection.Where(item => item.Date == ).ToList();
//DTOview = new ObservableCollection<DTOClass>();
//IEnumerable<DTOClass> DTOview2;
//List<IEnumerable<DTOClass>> FilteredView = new List<IEnumerable<DTOClass>>();
/*
if (Stock_ComboBoxText != null)
{
//var collection = DTO;
var collection = DTO.Where(item => item.stock_symbol == Stock_ComboBoxText).Cast<DTOClass>().ToList();
//DTOview.Add(filtered.Cast<DTOClass>());
//FilteredView.Add(collection.Cast<DTOClass>());
FilteredView.Add(collection);
MainGrid.ItemsSource = FilteredView[0];
//FilteredView = filtered.Cast<DTOClass>();
}
if (Maxadj_ComboBoxText != 0)
{
var collection = DTO.Where(item => item.stock_price_adj_close == Maxadj_ComboBoxText).Cast<DTOClass>().ToList();
FilteredView.Add(collection);
MainGrid.ItemsSource = FilteredView[0];
//DTOview.Add(DTO.Where(item => item.stock_price_adj_close == ).ToList());
}
if (From_DatePickValue != null)
{
var collection = DTO.Where(item => item.Date >= From_DatePickValue).Cast<DTOClass>().ToList();
FilteredView.Add(collection);
MainGrid.ItemsSource = FilteredView[0];
}
if (To_DatePickValue != null)
{
var collection = DTO.Where(item => item.Date <= To_DatePickValue).Cast<DTOClass>().ToList();
FilteredView.Add(collection);
MainGrid.ItemsSource = FilteredView[0];
}
*/
//DTOview = DTOViewInternal;
//DTOview = null;
//DTOClass[] dto = GetDTOClass();
//ListCollectionView collectionView = new ListCollectionView(DTOViewInternal);
/*
collectionView.Filter = (e) =>
{
//int j = DTO.Length;
DTOClass[] dtofiltered = e as DTOClass[];
//for (int i = 0; i < j; i++)
//{
if ((Stock_ComboBoxText != null) && (DTOview[0][i].stock_symbol == Stock_ComboBoxText))
{
return true;
}
if ((Maxadj_ComboBoxText != 0) && (DTOview[0][i].stock_price_adj_close == Maxadj_ComboBoxText))
{
return true;
}
if ((From_DatePickValue != null) && (DTOview[0][i].Date >= From_DatePickValue))
{
return true;
}
if ((To_DatePickValue != null) && (DTOview[0][i].Date <= To_DatePickValue))
{
return true;
}
}
return true;
};
*/
//return collectionView.Cast<DTOClass>().ToList();
//return collectionView.Filter;
//return null;
//MainGrid.ItemsSource = null;
//MainGrid.ItemsSource = (CollectionView)CollectionViewSource.GetDefaultView(collectionView.ToString());
}
else
{
//MainGrid.ItemsSource = DTOview[0].ToList();
//MainGrid.ItemsSource = DTOview;
//return DTOview[0].ToList();
return _CollectionViewInternal;
}
return _CollectionViewInternal;
}
I only want to filter on a column, if it's relevant checkbox is checked. This is easy pickings with one filter, but more than one is proving to be beyond challenging.
As you can see I have attempted numerous solutions. I have tried using an ObservableCollection, I have tried filtering the object list directly and then adding it to an ICollectionView. Nothing works.
I have been attempting to graft this example: Complicated Filtering ICollectionView. But I cannot make heads or tails of it. I still don't understand predicates and tbh I really can't wrap my head around how it works.
I know it's frowned upon to ask 'gimme the code' questions. But if someone could just see past that and point out what I am doing wrong here, maybe even give me the code, I would be very grateful. I have spent weeks trying to understand this and I have run out of time on this assignment.
If not, then that's cool but please refrain from commenting on this thread. Don't take pride in withholding the answer either, I am usually an embedded C programmer and I just finished a full-sized OSX-Windows port for a massive Adobe AfterFX plugin. So I don't need snide remarks or any nonsense about putting more effort into learning, I just want to finish this assignment and be done with it.
Thank you all in advance.
Code to complement above comment:
List<Predicate<IEnumerable<DTOClass[]>>> FilteredView = null;
public ICollectionView FilterView(DTOClass[] DTO)
{
List<Predicate<IEnumerable<DTOClass[]>>>FilteredView = new
List<Predicate<IEnumerable<DTOClass[]>>>();
FilteredView.Clear();
if (Stock_CheckBox.IsChecked != null)
{
FilteredView.Add(new Predicate<IEnumerable<DTOClass[]>>(x => x.Where(item => item.stock_symbol == Stock_ComboBoxText)));
}
}
I can't even get the first predicate working. Apparently .stock_symbol isn't there and I can't index item. I suppose my real question here is how do I access the stock_symbol member?
Apologies for taking so long to get there, I am extremely sleep deprived.
EDIT:
Dumb mistakes are made with no sleep.
List<Predicate<DTOClass>> FilteredView = new List<Predicate<DTOClass>>();
if (Stock_CheckBox.IsChecked != null)
{
for (int i = 0; i < DTO.Length; i++)
{
FilteredView.Add(new Predicate<DTOClass>(x => x.stock_symbol == _Stock_ComboBoxText));
//FilteredView.Add(new Predicate<DTOClass[]>>(x => x.stock_symbol == _Stock_ComboBoxText));
}
}
I am trying to stop my custom OnSaving event after it has been applied to the first item in the save chain.
but so far I have not been able to, and I end up with a stackoverflow exception.
Is there a simple way of doing this ?
Best regards,
Robin
private void AddOrRemoveRedirectingItemIdFromSavingItemIdList(Item savingItem, SitecoreEventArgs sitecoreEventArgs)
{
ItemLink[] referers = Globals.LinkDatabase.GetReferrers(savingItem);
var guidList = new List<ID>();
foreach (ItemLink link in referers)
{
// checking the database name of the linked Item
if (!link.SourceDatabaseName.Equals(Context.ContentDatabase.Name, StringComparison.CurrentCultureIgnoreCase))
{
continue;
}
Item item = Context.ContentDatabase.Items[link.SourceItemID, savingItem.Language];
// adding the Item to an array if the Item is not null
if (item == null || item.Fields["301Redirect"] == null || item.Fields["301RedirectedTo"] == null)
{
continue;
}
// Update the saving item ids
CheckboxField redirectField = item.Fields["301Redirect"];
if (redirectField.Checked)
{
guidList.Add(item.ID);
}
}
if (guidList.Any())
{
this.SaveIDsToEditingItem(savingItem, guidList, false);
}
}
private void SaveIDsToEditingItem(Item editingItem, IEnumerable<ID> guidList, bool forceModified)
{
Field redirectedToFromItemId = editingItem.Fields["301RedirectedToFromItemId"];
using (new EditContext(editingItem))
{
// Saving the redirected items ids
string redirectedToFromItemIdOld = redirectedToFromItemId.Value;
string redirectedToFromItemIdNew = string.Join("\n", guidList.Select(guid => guid.ToString()));
// if the values are not changed
if (redirectedToFromItemIdNew.Equals(redirectedToFromItemIdOld))
{
return;
}
redirectedToFromItemId.Value = redirectedToFromItemIdNew;
if (forceModified)
{
editingItem.RuntimeSettings.ForceModified = true;
}
}
}
}
You can do this 2 ways. The better way would be to remove the using (new EditingContext(editingItem) section from the SaveIDsToEditingItem. In the OnItemSaving event, any changes made to the savingItem would be kept.
Alternatively, if you need to use the editing context for some reason you need to use an EventDisabler in your SaveIDsToEditingItem method:
private void SaveIDsToEditingItem(Item editingItem, IEnumerable<ID> guidList, bool forceModified)
{
Field redirectedToFromItemId = editingItem.Fields["301RedirectedToFromItemId"];
using (new EventDisabler())
{
using (new EditContext(editingItem))
{
// Saving the redirected items ids
string redirectedToFromItemIdOld = redirectedToFromItemId.Value;
string redirectedToFromItemIdNew = string.Join("\n", guidList.Select(guid => guid.ToString()));
// if the values are not changed
if (redirectedToFromItemIdNew.Equals(redirectedToFromItemIdOld))
{
return;
}
redirectedToFromItemId.Value = redirectedToFromItemIdNew;
if (forceModified)
{
editingItem.RuntimeSettings.ForceModified = true;
}
}
}
}
This will prevent the OnSaving event from being fired again.
I wasn't the one who coded this line of code, and I can't gt to understand whoever did it, why did this way on this line: res.Data.Find(itm => itm.Meta.ID.ToUpper() == i["MetaDataID"].ToString().ToUpper()).Value[i["LocaleID"].ToString()] = i["Value"].ToString();
And this line gives me a NullReferenceException. How can I get around it?
public static void LoadData(Value.Item _res)
{
DataTable Res = Connector.Run("SELECT * FROM Data WHERE ItemID='" + _res.ID + "'");
if (Res.Rows.Count != 0)
{
foreach (DataRow i in Res.Rows)
{
try
{
_res.Data.Find(itm => itm.Meta.ID.ToUpper() == i["MetaDataID"].ToString().ToUpper()).Value[i["LocaleID"].ToString()] = i["Value"].ToString();
}
catch (Exception)
{
_res.Data.Add(new Value.Data(
i["ID"].ToString(),
i["Value"].ToString(),
i["LocaleID"].ToString(),
i["MetaDataID"].ToString()
));
}
}
}
}
Thx a lot guys!!! Here is my working solution which hrows no Exceptions anymore!
public static void LoadData(Value.Item _res)
{
DataTable Res = Connector.Run("SELECT * FROM Data WHERE ItemID='" + _res.ID + "'");
if (Res.Rows.Count != 0)
{
foreach (DataRow i in Res.Rows)
{
bool _flagged = false;
var _result = _res.Data.Find(itm => itm.Meta.ID.ToUpper() == i["MetaDataID"].ToString().ToUpper());
if(_result != null && i["LocaleID"] != null)
{
if (i["Value"] == null || i["LocaleID"] == null || i["MetaDataID"] == null)
_flagged = true;
}
else
{
_flagged = true;
}
if (_flagged)
{
_res.Data.Add(new Value.Data(
i["ID"].ToString(),
i["Value"].ToString(),
i["LocaleID"].ToString(),
i["MetaDataID"].ToString()
));
}
//try
//{
// _res.Data.Find(itm => itm.Meta.ID.ToUpper() == i["MetaDataID"].ToString().ToUpper()).Value[i["LocaleID"].ToString()] = i["Value"].ToString();
//}
//catch (Exception)
//{
// _res.Data.Add(new Value.Data(
// i["ID"].ToString(),
// i["Value"].ToString(),
// i["LocaleID"].ToString(),
// i["MetaDataID"].ToString()
// ));
//}
}
}
}
Impossible to answer accurately without having the code under the debugger, however what is certain is that at least one of the following has a value of null:
_res.Data
itm.Meta
itm.Meta.ID
i["MetaDataID"]
i["LocaleID"]
i["Value"]
Old-skool debugging:
Break the statement down to it's consituent parts - using local variables. Step-through and find which one is null.
Check if one of the following are null:
i["MetaDataID"]
i["LocaleID"]
i["Value"]
i'm working on an winform(mdi) pro. And I need to update a dataGridView control when i get new data from another thread. and when new data comes and i'm dragging the dataGridview scroll, it throw a nullreference exception in dataGridView.Invoke. i have searched for few days and drove google crazy,but didn't help.
the code like this:
public void ReceiveNewData(object sender, UpateEventArgs ex)
{
if (this.dataGridView.InvokeRequired)
{
dataGridView.Invoke(new UpateEventHandler(ReceiveNewData), new object[] { this, ex });
}
else
this.BindNewData();
}
private void BindNewData()
{
if (dataGridView!= null && (QuoteMember.listOneClickQuoteItem != null || QuoteMember.listMarketingQuoteItem != null))
{
DataTable dataSource = PublicFunction.ToDataTable(QuoteMember.listOneClickQuoteItem);
if (dataSource != null)
dataSource.Merge(PublicFunction.ToDataTable(QuoteMember.listMarketingQuoteItem), true);
else
dataSource = PublicFunction.ToDataTable(QuoteMember.listMarketingQuoteItem);
dataGridView.DataSource = dataSource;
}
}
public PublicFunction
{
public static DataTable ToDataTable(List dataSource)
{
if(dataSource != null)
return ToDataTable((dataSource.ToArray()), 1);
return null;
}
public static DataTable ToDataTable(List dataSource)
{
if (dataSource != null)
return ToDataTable((dataSource.ToArray()), 2);
return null;
}
private static DataTable ToDataTable(QuoteItemBase[] m, int type)
{
DataTable dsTemp = null;
if (type == 1)
{
dsTemp = new DataTable("OneClickQuote");
}
else if (type == 2)
{
dsTemp = new DataTable("MarketingQuote");
}
else
dsTemp = new DataTable("temptable");
dsTemp.Columns.Add("Date");
dsTemp.Columns.Add("Time");
dsTemp.Columns.Add("NO");
dsTemp.Columns.Add("Name");
if (m == null)
return dsTemp;
foreach (var item in m)
{
DataRow drTemp = dsTemp.NewRow();
drTemp["Date"] = item.date;
drTemp["Time"] = item.time;
drTemp["NO"] = item.no;
drTemp["Name"] = item.name;
dsTemp.Rows.Add(drTemp);
}
return dsTemp;
}
}
PS:
if new data comes and i'm not dragging scroll bar, it works fine.
any ideas?
thank you !
I found that when you invoke a control and set bindings (or clear them)
and an object is set to null this can throw a null reference exception, this is reflected through invoke giving an error, this error however is somewhere else in your code:
quick example:
public class test : Form
{
public test()
{
Thread t = new Thread(start);
t.Start();
}
public void start()
{
LoadCompleteEvent();
}
public void LoadComplete() //fired by LoadCompleteEvent();
{
if(this.InvokeIsRequired)
{
//do invoke
//and return
}
comboBoxEditBrand.Properties.Items.Clear();
comboBoxEditBrand.Properties.Items.AddRange(ListOfStuff.ToArray());
}
public void comboBoxEditBrand_SelectedItemChanged(object sender, eventargs e) // fired as control is changed
{
//error here!!
if(comboBoxEditBrand.SelectedItem == SomeBrandItem) //<- this is where the error is thrown!! check for null first!
{
//do something
}
}
}
it's something like this.. this code will probably not throw the error because A) it's from the top of my head and B) it's made up. BUT this is kind of what bugged me for half a morning as to WHY this error was thrown.
just place
if(comboBoxEditBrand.SelectedItem == null)
return;
where it says //error here!! and it should work again.
Make sure you switch to the Gui thread before you invoke