This thread looks to be a little on the old side and therefore may no longer be relevant. Please see if there is a newer thread on the subject and ensure you're using the most recent build of any software if your question regards a particular product.
This thread has been locked and is no longer accepting new posts, if you have a question regarding this topic please email us at support@mindscape.co.nz
|
I'm doing a sample project that uses a VistaDB database. I tried connecting the object model to the GUI but it's working only if I connect it through a BindingSource and deletes and inserts are not sent back to the database.
Here's the code I use b = new BindingSource(); var results = from p in _uow.Glossaries select p; _uow is my unit of work. If I try to assign the results directly as the datasource property of the dataGridView no row is displayed. Am I missing something? Thank you. |
|
|
Is anybody caring to answer my question after 4 days? I'm considering using your solution to build a commercial application if it works and, on top of that, if customer care answers my questions. Thank you. |
|
|
Hello Andrea, Sorry for the slow reply, it has been a public holiday here. The problem is that the grid's source is a query. Effectively the BindingSource is executing the query and taking a snapshot of the results. When you insert or delete items in the grid, those are getting added to and removed from the BindingSource's snapshot, not the unit of work. (And I think setting the grid DataSource directly doesn't work because the query is a LINQ query and therefore not bindable.) I'm not deeply familiar with Windows Forms data binding, but I think the best solution for this is to use a BindingList. The idea is to call IUnitOfWork.Add and IUnitOfWork.Remove as items are added to and removed from the BindingList. Unfortunately, using a plain BindingList<T> doesn't work very well for this because the ListChanged event doesn't tell you which item has been added or removed -- not a problem for Add because you can still get it from the list, but a bit of a problem for Remove because by the time the event is raised the item is gone from the list. My workaround for this is to subclass BindingList<T> and override the RemoveItem and InsertItem methods to invoke the corresponding methods on the unit of work: public class UowWrappingBindingList<T> : BindingList<T> With this class at hand, I can write the following in my form load code: dataGridView1.DataSource = new UowWrappingBindingList<Glossary>( Now when I edit, add or delete in dataGridView1, the changes are synchronised to the unit of work. And when I call _unitOfWork.SaveChanges() the inserts, updates and deletes are saved to the database. Note that you only need to muck around with UOW synchronisation calls for top-level queries. Collection associations automatically implement IBindingList and synchronise changes to the unit of work. Also note that I am using a long-running unit of work here. This is convenient when data synchronisation and concurrency are not issues, but for a more scalable application you will want to use short-running units of work; however getting these to work with data binding is a bit more complicated. Hope this helps and please let us know if you have any further questions. |
|
|
Thanks for your reply (I didn't know it was holiday in New Zealand). The behavior you are describing is different from the one I experienced with another ORM framework (PLINQO) where I can attach the results directly to the grid and I'm able to modify, add and remove records without doing the operations you suggested. So, you commend that I keep only one unit of work object thought the life of the application? But would this be a problem if many users are accessing the DB (my application is using VistaDB). What would be the standard way to do things in that situation? It looks to me that the major problem is with inserts and deletes of records. Thanks a lot. Andrea PS: will I be able, using your solution of seamlessly attach either to a SQLServer database or a VistaDB database? |
|
|
We do actually normally recommend short-lived units of work for exactly the reason you describe -- multiple users accessing the database at the same time. However depending on your UI pattern it can be a bit harder to make data binding work with short-lived units of work. If you're applying changes to the database directly then it's okay, but things get a bit trickier if you want to batch up a bunch of inserts, updates and deletes and save them all in one go. If you let us know which pattern you're using we can provide a bit more advice. I can't really comment on PLINQO, but going by their Web site they are basically a layer on top of LINQ to SQL. LINQ to SQL makes it easier to bind top-level query results than LightSpeed does (improving this is on our backlog), but I believe this will only work as long as you use a long-running data context: if you dispose the data context after loading and recreate new data contexts only when you need to do a save, then add-remove via data binding won't work. I could be wrong about this though! Yes, LightSpeed will normally work seamlessly as you switch between databases. (The exceptions are generally around database features -- e.g. code which uses stored procedure queries won't run against SQLite.) Switching between VistaDB and SQL Server should just be a matter of changing some configuration settings. That said, it's obviously important to test on all target platforms. Specifically, we are aware of some performance issues in VistaDB around subqueries which affected LightSpeed eager loading, though that was a few months back and these may have been resolved by now. |
|
|
Thanks a lot for the information. I'll start building my BL using your solution (I'm migrating from a system that uses datasets). |
|
|
Normal 0 false false false EN-US X-NONE X-NONE MicrosoftInternetExplorer4 <!-- /* Font Definitions */ @font-face {font-family:"Cambria Math"; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:1; mso-generic-font-family:roman; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:0 0 0 0 0 0;} @font-face {font-family:Calibri; panose-1:2 15 5 2 2 2 4 3 2 4; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:-1610611985 1073750139 0 0 159 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:""; margin:0in; margin-bottom:.0001pt; line-height:115%; mso-pagination:widow-orphan; font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;} .MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;} .MsoPapDefault {mso-style-type:export-only; line-height:115%;} @page WordSection1 {size:8.5in 11.0in; margin:1.0in 1.0in 1.0in 1.0in; mso-header-margin:.5in; mso-footer-margin:.5in; mso-paper-source:0;} div.WordSection1 {page:WordSection1;} --> /* Style Definitions */ table.MsoNormalTable {mso-style-name:"Table Normal"; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso-style-priority:99; mso-style-qformat:yes; mso-style-parent:""; mso-padding-alt:0in 5.4pt 0in 5.4pt; mso-para-margin:0in; mso-para-margin-bottom:.0001pt; line-height:115%; mso-pagination:widow-orphan; font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:"Times New Roman"; mso-fareast-theme-font:minor-fareast; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin;} Thank you for sharing your helpful advice above with respect to connecting to a datagrid and updating data.
I am trying to emulate your methodology in a small test app to help myself understand once and for all how to connect Mindscape Lightspeed, MySql, and DevExpress datagrids into a fully functional CRUD application.
Situation:
using System.ComponentModel; using Mindscape.LightSpeed;
Namespace is "MyLSDDevExCRUD" lsmodel is "Model" and named "Test_CRUD") in the App.config file MySQL database is "menagerie" (from MySQL's intro tutorial) MySQL table is "critters" and the LS Entity is "Critter" The unit of work I have selected is named "uowGrid" The DevExpress datagrid is called "gridControl1"
Here is the project code that I put together so far that is relevant: (I did copy and paste your class definition for UowWrappingBindingList and added it to the project).
But there is one line where the build fails, and I can't see the obvious as to why. Perhaps it is that I am mis-understanding your solution above as I don't know that poster's LS Model structure, but I assumed it contained an Entity called "Glossary" and referenced a table called "Glossaries"
The problem comes in the line in the form initialization section: gridControl1.DataSource = new UowWrappingBindingList<Critter>(uowGrid,uowGrid.critters); where the second paramter "uowGrid.critters" is rejected by the compiler.
And I don't know how to rectify that. Obviously, I am mis-understanding something or simply don't understand something.
Your advice would be much appreciated.
namespace MyLSDevExCRUD { public partial class Form1 : Form { private static LightSpeedContext<ModelUnitOfWork> _context;
IUnitOfWork uowGrid;
public Form1() { InitializeComponent();
_context = new LightSpeedContext<ModelUnitOfWork>("Test_CRUD"); uowGrid = _context.CreateUnitOfWork(); gridControl1.DataSource = new UowWrappingBindingList<Critter>(uowGrid,uowGrid.critters);
}
//I have a button on the GUI to load the grid public void btnLoadCritters_Click(object sender, EventArgs e) {
gridControl1.DataSource = uowGrid.Find<Critter>();
}
//The DevExpress Grid has embedded navigation buttons, and I have evoked them. private void gridControl1_EmbeddedNavigator_ButtonClick(object sender, DevExpress.XtraEditors.NavigatorButtonClickEventArgs e) { //EndEdit button on embedded navigator if (e.Button.ButtonType == DevExpress.XtraEditors.NavigatorButtonType.EndEdit) { uowGrid.SaveChanges(); }
|
|
|
I copied and pasted form MS Word. Sorry for all that html stuff. I didn't know it would do that. My apology. Kenneth James |
|
|
That looks fine to me, except that if the LightSpeed entity is Critter with a capital C, then the corresponding unit of work property should be Critters also with a capital C. The property is always the plural of the entity name, not the raw table name. Thus: gridControl1.DataSource = new UowWrappingBindingList<Critter>( Could that be the problem or was the lower-case "c" just a typo? If this isn't the problem, could you post the compiler error please? Thanks! |
|
|
Thanks for the reply. I had tried every combination I could think of, and here is the error message when I use the plural of the LightSpeed Entity (which is Critter).
Error 1 'Mindscape.LightSpeed.IUnitOfWork' does not contain a definition for 'Critters' and no extension method 'Critters' accepting a first argument of type 'Mindscape.LightSpeed.IUnitOfWork' could be found (are you missing a using directive or an assembly reference?) C:\Users\KDJ\Documents\My Dropbox\MyLSDevExCRUD\Form1.cs 31 83 MyLSDevExCRUD
When typing in that parameter, uowGrid. and when hitting the period, the IntelliSense gives nothing that resembles anything specific to "Critter" or "Critters" or "critter" or "critters" (where "critters" is the raw table name. I sounds like something is out of scope here, and I don't know what or where to fix it. Kenneth James. |
|
|
Aah, I see it. Your uowGrid member is declared as IUnitOfWork rather than ModelUnitOfWork. So although _context.CreateUnitOfWork() returns a ModelUnitOfWork (which does have a Critters member), the compiler only knows that uowGrid is an IUnitOfWork (which doesn't). Change your declaration of uowGrid to be of type ModelUnitOfWork and all should be well. Sorry I didn't spot that first time around! |
|
|
Well, that change certainly fixed it. Thank you :) Kenneth James |
|