[RESOLVED] binding navigator to binding source to linq-to-sql
ok so this has been a solid week at least of frustration with implementing any kind of cancel changes with this combo.
- CancelEdit on the bindingsource only seems to work on things like textboxes, and specifically not on comboboxes in drop down mode.
- there's no cancelChanges on a linq to sql object.
- disposing your datacontext and refreshing it would throw away your local cache of objects, and/or orphan them from being able to traverse their foreign key properties right?
linq to sql is just too much damn better than having strings in your code, or having to provide a special data adapter for every possible query combination for strongly typed datasets.
But I can't find a decent way to implement allowing a user to save changes or cancel them whether I try to do it at the record level, or allowing a user to change lots of records and only then choosing to save. My concern for allowing the user to change multiple records would be that one change is rejected, blocking any of the changes from working, and the exception doesn't provide which control, or which record the error is on, so I have NOTHING to show the user to help them fix the problem.
I built a buffering system so that every change that is made is made to a business object. but it seemed like a crapload of code just to achieve rollback functionality that a dataset already had natively. Maybe to use linq to sql this way you have to use a stupid dataset on top of your linq to sql to get reject changes capability? I'm just not finding the way this is supposed to work.
Any knowledge or ideas?
Re: binding navigator to binding source to linq-to-sql
Consider how ADO.NET works. The DataTable class contains DataRows. Once you make a change to a DataRow there's no cancelling it. ADO.NET also provides the DataView class, which provides a view of the data in a DataTable. The DataView contains DataRowViews, each of which provides a view of the data in a DataRow. It's the DataRowViews that provide the ability to cancel changes through their implementation of the IEditableObject interface. If you want similar functionality then you would need to implement something similar.
Re: binding navigator to binding source to linq-to-sql
Quote:
Originally Posted by
jmcilhinney
Consider how ADO.NET works. The DataTable class contains DataRows. Once you make a change to a DataRow there's no cancelling it. ADO.NET also provides the DataView class, which provides a view of the data in a DataTable. The DataView contains DataRowViews, each of which provides a view of the data in a DataRow. It's the DataRowViews that provide the ability to cancel changes through their implementation of the IEditableObject interface. If you want similar functionality then you would need to implement something similar.
I haven't worked with a DataView or DataRowView, only datatable, dataSet and a strongly typed dataSet. It sounds like you're saying I do need to wrap a linq to sql row in a buffered business object so that changes are buffered and only saved if the user asks for it. I guess I'll go back to that paradigm, I gave up on it thinking this is way more work that I imagined would need to be done. I thought I must just not know the tricks to using linq-to-sql or a bindingsource well enough to accomplish this without implementing my own edit buffering. Luckily I've got source control, and haven't deleted the class that was doing the buffering.
Re: binding navigator to binding source to linq-to-sql
If you've ever bound a DataTable then you've used a DataView, even if you didn't know it. When you bind a DataTable it's the contents of its DefaultView that is actually used. That's how you're able to cancel edits made through bound controls.
If this is something you're likely to do again then I'd suggest creating your own code generator. Create a tool that you can pass a class to and it will spit out the source code for a corresponding view class that implements IEditableObject.
Re: binding navigator to binding source to linq-to-sql
I googled IEditableObject, read this article it appears what IEditableObject is supposed to do is added EndEdit and CancelEdit to an object... isn't this what the bindingSource does? how come it isn't working?
I have rolled my own buffering class, that's a little messy but works for sure saving one record at a time.
This is the parent class for my business objects that wrap around a linq entity.
Code:
public class BufferedLinqChange
{
LqGpsDataContext _dataContext;
internal BufferedLinqChange(LqGpsDataContext dataContext)
{
_dataContext = dataContext;
}
protected void SetBufferedProperty<T>(string key,Action linqAction
,bool linqEqualsValue,Action bufferAction)
{
if (linqEqualsValue)
{
if (Changes.ContainsKey(key))
Changes.Remove(key);
}
else
Changes.InsertOrUpdate(key, linqAction); bufferAction();
}
protected Dictionary<String, Action> Changes = new Dictionary<string, Action>();
public int ChangeCount { get { return Changes != null ? Changes.Count : 0; } }
public bool hasChanges { get { return Changes != null ? Changes.Count > 0 : false; } }
public void SubmitChanges()
{
_dataContext.SubmitChanges();
if (ChangeCount > 0)
{
Changes.ForEach((item) => item.Value.Invoke());
_dataContext.SubmitChanges();
}
}
public void CancelChanges()
{
if (Changes != null)
Changes.Clear();
}
}
Here's a sample of one of the properties:
Code:
#region assetTag
String _AssetTag;
public const String STR_assetTag = "assetTag";
public String assetTag
{
get { return (Changes.ContainsKey(STR_assetTag) ? _AssetTag : Asset.assetTag); }
set
{
SetBufferedProperty<String>(STR_assetTag
, () => Asset.assetTag = value, Asset.assetTag == value, () => _AssetTag = value);
}
}
#endregion
so far it is working well.
Re: binding navigator to binding source to linq-to-sql
Quote:
Originally Posted by
MaslowB
I googled IEditableObject, read
this article it appears what IEditableObject is supposed to do is added EndEdit and CancelEdit to an object... isn't this what the bindingSource does? how come it isn't working?
As I do so often, I recommend that you read the relevant documentation. This is from the documentation for the BindingSource.CancelEdit method:
Quote:
Originally Posted by MSDN
This method discards modifications to data since the last save or load operation if both of the following conditions are met:
The data source implements the IEditableObject interface.
The EndEdit method has not been called yet.
This method calls the CancelCurrentEdit method of the underlying CurrencyManager, and is scoped to row-level changes.
The BindingSource contains no data of its own. It just provides a layer for the data to pass through. It can't make a data source support transactional editing if it doesn't already.
Re: binding navigator to binding source to linq-to-sql
well... that was simple to implement, all that remains is deciding if I should implement BeginEdit or leave it alone so that all changes are buffered instead of immediately committed.
Thanks.