I am creating a database application using Visual C# Express and MySQL. The issue is that I only want to store data to the database from the C# forms if the data has actually been changed, the way I do it now is that when the 'Save' button is clicked all the all the fields in the form are saved into the database, whether or not they have been changed.
The solution I have come up with is just to check for every field in the form if it has been changed and then change the SQL command accordingly, i.e.
//when the details are loaded into the form
String strOriginalName = txtFirstname.Text;
//when the save button is checked
if(strOriginalName != txtFirstname.Text)
{
String strUpdate = "UPDATE table SET firstName = txtFirstname.Text";
MySqlCommand cmdUpdate = new MySqlCommand(strUpdate, connection);
cmdUpdate.ExecuteNonQuery();
}
Does anyone else have a better or alternative solution? Thank you for your help, if I was vague in any part, please let me know and I can try explain further.
I suggest to use some OR Mapper (NHibernate) for example. It will do it all for you. In addition this will give you caching and other cool things for free :)
Lessons learned for future are priceless and your next applications will be grow faster and faster. :)
Have a single update query - unless you have hundreds of parameters, you shouldn't see much of a performance issue.
In the class that you want to update, have a boolean dirty flag that will be set to true whenever a value changes.
Only update to the database when the flag is indeed true.
Alternatively, use an ORM that implements Unit Of Work, which should handle this for you automatically.
If you have single field in the form then this is correct...
but when you have multiple values(fields) in your form then you should use 1 flag variable.
Once any text is changed you should set that flag to true and update it..
Look at the way ORMs implement this feature,
Search for NotifyPropertyChanged and Object Change Tracking.
Related
My program has an entity call Articles. In one form the user can specify how many new articles he wants to buy. This happens in a form called "Purchase order". So, when that happens, the stock musk increase. In another form, where I list all the articles, it must reflect that change.
Now, this is my problem. After I generate the purchase order, if I go to the SQL and I search that article in my DB, I can see the change. If go to my form, where I list the articles, I cant see that change. But, if I close the program and then I run it again, if I search the article, the change appears.
I don't know what could be the mistake. I'm using Entity Framework.
This is how I add the article.
BaseRepository.BeginTransaction();
foreach (Documento_Articulo doc in datos.Documento_Articulo)
{
if (!articuloRepository.Increase(doc.Articulo.Id_Articulo, doc.Cantidad))
{
BaseRepository.RollBackTransaction();
return response.Error("Error: - " + doc.Articulo.Descripcion);
}
}
response.Value = documentoRepository.InsertGetDocument(datos);
BaseRepository.CommitTransaction();
I think that code does not have a problem, because as I say, I can see the change in my database.
Does anybody knows why this happens?
I suspect the client caches the results. If you set a breakpoint in the method which returns the list from the db, is it executed every time you display the it?
This is a contrived example however I have simplified it for ease of explanation.
Please see my update at the bottom before investing too much of your
time!
Background
I have some (a lot of) code that ordinarily queries my DB as follows:
SELECT name FROM sites where IsLive=1;
My challenge is to, under certain conditions, return the full list of sites, essentially
SELECT name from sites;
I do not wish to modify the actual C# code issuing the SQL (although I can do if I have to in order to achieve my goal which is purely for demonstration purposes).
Therefore in order to leave as much untouched as possible my thoughts are to insert a database-proxy-view called site that returns the data dependent on a control variable
Method
Rename existing site table to site_table
Create a new view named site that the C# code now unknowingly targets and which returns the (possibly filtered) details from site_table according to the control variable value (Note a limitation on variables in views meant I had to create a function in order to demonstrate this - see http://dev.mysql.com/doc/refman/5.7/en/create-view.html wrt error 1351)
Changes made
ALTER TABLE site RENAME TO site_table;
CREATE FUNCTION controlVariableFn() RETURNS VARCHAR(16) RETURN #controlVariable;
CREATE OR REPLACE VIEW site AS SELECT * from site_table WHERE (IsLive = 1 OR controlVariableFn() = 'SHOWALL');
The above statements are ugly but achieve the result I want, however my problem is to dynamically pass through controlVariable without changing my main SQL queries being sent.
My Question
Is there a way to (ideally as I am creating my connection object) define the controlVariable outside the actual SQL to be executed but which the View can still access similar to the above as though it had been supplied as a regular user variable parameter to the query?
so the code would look something like
var connectionString = "Server=localhost;User ID=un;Password=pw;Database=dbname;....";
DbConnection db = new MySql.Data.MySqlClient.MySqlConnection
(connectionString, "controlVariable=SHOWALL");
var results = db.Query<Site>("SELECT * FROM site;");
(I understand that this would not be a smart permanent solution)
Update
My preferred solution as outlined above will not work for me as once I get into my data access layer as the results set will
essentially be filtered again back to the original set. There are some circumstances where it
could work; it would depend on the SQL issued (e.g. when collapsing a
results set down instead of trying to expand a results set as I was
trying to do here).
In that regard I am no longer looking for an answer here but will leave it for posterity as a preferred option and as per the guidelines - thanks anyway.
If you do not want to edit the c# code then the variable will have to be stored in the database although i am not sure how you will not edit the code.
If you are willing to edit the code then you can access a secondary configuration table which will have the settings that you would like the user to pass to the view. take this and allow the user to select which they want and then pass it to the view through the application.
I am using entity framework database first and extending the AutoGenerated partial classes. Is the following alright if I need to also set the property in my application based on certain scenarios? It just feels strange because I am usually setting a private property in my set, but don't think I need to here with EF.
public string FullName
{
get
{
return string.Format("{0} {1}", FirstName, LastName);
}
set
{
}
}
In my application FullName is a bound field in a grid. When I bind the grid from the database it works fine as a read-only property. But there is an instance where I have to dynamically create an objectlist of CustomerContact and pass it to another page in a Session variable and bind the grid in memory on the new page. Since the bound field for the same column in the grid on the new page needs to be FullName it seems like I have no option but to allow a Set on this property...
Based on the comments. No you should not leave it empty.
Think about it from a user point of view.
You can say MyThingy.FullName = "Fred Blogs". It compiles, it throws no exceptions and does absolutely nothing.
Other people's code, which includes your own in a couple of months, is hard enough to understand without drilling big holes in your cortex before you start.
To beef up from your last comment. No it doesn't make sense to have one class that has two completely different behaviours. There are lots of ways to deal with this sort of scenario, but making one object that implements both behaviours poorly isn't a good choice.
Hard to say which option would be best, but a DTO (Data Transfer Object) with a converter from and perhaps to the EF representation would be a much better solution than leaving a huge hole in the logic to fall into later.
I'm new here this is my first question and I beforehand apologize for any lack of information, search or tags in the post or anything at all.
I'm writing a pretty simple winforms program, and I'm having problems with cascading combo boxes, pretty much like country>Estate>City I'm new to this, I'm using Entity Framework and I'm getting by with something like this:
private void Form_CadAnimal_Load(object sender, EventArgs e)
{
using (DbClinvetEntities ctx = new DbClinvetEntities())
{
cmb_especie.DataSource = ctx.Especie;
cmb_especie.DisplayMember = "Nome";
cmb_especie.ValueMember = "EspecieID"
cmb_raca.DataSource = ctx.raca;
cmb_raca.DisplayMember = "Nome";
cmb_raca.ValueMember = "RacaID";
}
}
So far so good all is going ok, I get them to be populated, I've found countless posts on the matter, but perhaps for lack of knowledge I could not relate them to my situation.
now all I would like to do is filter cmb_Raca by the value selected in cmb_Especie, just to make it clearer Raca table has a foreign key on Especie table, pretty much like you would expect country>estate to be.
I've found posts where a new context is generated on SelectedIndexChanged and a whole new binding is done, but I wonder if there is a way to make this work without making further calls to the Db, any way to take the list of objects and work them offline after the first access?
Sorry if this is anyhow unclear, I'll glady edit the post to provide further information if necessary.
try using the SelectedIndex as your query select command.you can build a module for talking to the database that takes the SelectedIndex.ToString() as a parameter to build your Query and fill data to your form based on that. the Combobox doesn't necessarily have to be databound when it is used that way.
May sound like a dumb question but here goes.
I instantiate a LIST from my homepage, the list is in a global class file, and returns all the information about the person logging in. the person, could have one or more accounts associated with the site, and therefore i need to code against a default flag to display their default account informaiton. However, i then also need to build their other account information and display this for them.
The additional account(s) are listed in a drop down box. when the drop down box fires off, instead of calling out to the class again, and retrieving all the necessary information, as i've already done this once, how can i store the object, so that it can be used?
I've looked at Session Variables, but this gets a bit messy (I have 35 fields being returned in my list), plus, the Session variables only get set the first time around, not on DDL changed.
therefore, I need a way of having quick access to the object. - what's the best approach?
As per me , Session is the best possible object for your type of requirement and on DDL changed event try to rebind the Session object with new modified values