Can Linq-to-SQL Do an Insert or update as needed? - c#

I have a distributed app that sends data via WCF to a server to be stored in the database (SQL Server 2008).
Usually this data is new. So I just do InsertAllOnSubmit().
But occasionally, due to communication oddities with the handheld devices that run the client side I get an object that is already in the server.
Is there a way to say InsertOrUpdateAllOnSubmit? Or am I going to have to change my code to go through each object and check to see if it is in the database and then do and insert or update as needed? I have quite a few object types, so that will get tedious really fast :(

Change the store procedure on the database to handle Insert of duplicates.

Usually what I've seen as the pattern for the scenario when you attempt to do any kind of insert or update and there is conflict, such as objects already existing, then once you detect a conflict you request the new data and apply your updates to it. This allows you the flexibility of deciding which change wins, or prompting the user in some way letting them view the new data and decide if their data should win. It all depends on the context and business rules.
This mostly applies to updates but maybe if you think about why these conflicts are occurring for inserts you might be able to adapt your implementation to use concurrency detection and resolution techniques.
http://msdn.microsoft.com/en-us/library/bb399373.aspx

Related

Triggering event for SignalR

I am using SignalR to update client-side when data is changing on the backend. The data can be either from SQL Server or NoSQL DB.
What I am doing now is: I have a timer on the backend that constantly is trying to check whether there is a change in the DB and if it detects it then I allow SignalR to update the client-side.
I find this approach not good: the timer's interval value can't be really small e.g. even with 1 second I have a huge load on the DB. Besides, it's not real-time and even 1 second is too big. Additionally, that it's quite difficult to detect a DB change if it's not about adding a new record, but calculating some hash for all the records every 1 second or even less is surely not an option.
I think I used to read about another approach that is based on some event triggered either by the DB or by something else, but I can't remember this.
So I was wondering if somebody could advise me of a better solution.
I'm afraid we need to take different actions for different scenarios on this case.
As you mentioned that your data may come from SQL server and nosql db. So I think the scenario should like:
You write code to update the data in both of the database, if so, you can write the calling signalr code after the updating data code, so that you are no need to using trigger.
Based on the scenario 1 as well, if the database you used support using stored procedure, you may also try to find the possibility of writing stored procedure to call the signalr code.
You may also check if the databases you used have event like "data_onchange_event", this document is related to this scenario. I mean if the data stored in the database updated, your database will send an event, you can then write custom code to capture these event and then call signalr.
If you can't or don't write code to update your databases, then you may only using external trigger to monitor the database, but just like you mentioned in the question, it doesn't support high performance because of huge load on the DB. It's based on the database but not the external trigger.

Desktop application which can work offline when no connectivity with SQL Server

I am designing a WPF desktop application and using Entity framework Code First to create and use SQL Server Database. My database will be hosted on One Server machine and will be running 24*7.
I want to provide a feature, where you can modify data offline(when you have no connectivity with SQL Server DB) and Save it somehow. And whenever your application will find connection with SQL Server, all changes can be moved to SQL Server DB.
Is there any way to achieve this by using Entity Framework ?
I want to emphasis on the part that I am using Entity Framework. Is this type of functionality already implemented by EF?? Or I have to do it manually, like have to write that in any file system and then manually merge it later to DB ?
You could figure out the specific exceptions that are generated when the SQL Server connection is lost, and embed your calls in try-catch blocks. If the server is offline, then in your catch block, pass the entity to a method that serializes the entity to JSON and saves it to the hard drive in a special directory or something. On your next successful query, check that directory to see if there are any saved entities that need to be saved.
Be specific with your catches - you don't want unrelated exceptions to trigger this code.
Some things to keep in mind - what if somebody else changed the data in the meantime? Are you intending to overwrite those changes? How did you get the data which needs to be saved in the first place if you are offline?
As long as you have all data loaded into DbContext/ObjectContext you're free to amend those data anyway you want. Only when SaveChanges() is invoked, the connection is really needed.
However, if you're going to load everything into the context, you seem to reimplementing DataSet functionality, which, in addition, allows for xml serialization/deserialization of the changes, so the changes can be even saved between sessions.
Not as trendy as EF, though :)
While I have never tried this with SQL-based data I have done it in the past with filesystem-based data and it's a major can of worms.
First, you have to have some means of indicating what data needs to be stored locally so that it will be available when you're offline. This will need to be updated either all the time or before you head out--and that can involve a lot of data transfer.
Second, once you're back online there's a lot of conflict resolution that must be done. If there's a realistic chance that someone else might have changed the data while you were out you need some way of detecting the conflict and prompting the user as to what to do in that situation. This almost certainly requires a system that keeps a detailed edit trail on every unit of data that could reasonably be updated.
In my situation I was very fortunate in that it was virtually certain that if the remote user edited file [x] that overwriting the system copy was the right thing to do. Remote users would only be carrying the files that pertained to their projects, conflicts should never happen. Thus the writeback was simply based on timestamps, nothing more. Data which people in the field would not normally need to modify was handled by not even looking at it, modified files were simply copied from the system to the laptop.
This leaves the middle step--saving the pending writes. I disagree with Elemental Pete's answer in this regard--simply serializing them and saving the result them does not work because what happens when you read that data back in again? You see the old copy, not the changed copy!
My approach to this was a local store of all relevant data that was accessed exactly like the main system data was, all reads and writes worked normally.
Something a lot fancier might be needed if you have data that needs transactions involved.
Note that we also hit a nasty human problem: the update process took several minutes (note: >10y ago) simply analyzing what needed to be done, not counting any actual copy time. The result was people bypassing it when they thought they could. Sometimes they thought wrong, oops!

Design considerations for monitoring SQL database table changes

I am working on an assignment to monitor and log various "system-level messages” within our multi-tier .NET 4 WPF, WCF, SQL 2008 application. By messages, I mean details about an event that has occurred in our application, e.g. user logs in and out or data is saved. By logging, I mean that we will be inserting messages into a light-weight SQL table from which clients can poll and display the latest messages.
The source of these messages could come from several different components in our application e.g. Windows Services, WCF Host in IIS, and even stored procedures in the Database. Ultimately these components modify SQL tables each in their own way. So rather than attacking each of these components independently, I’m thinking I might be able to simplify things by saying that the messages need to be “triggered” when certain tables in SQL are modified (updated, inserted).
The first thing that comes to mind would be a trigger on each of the tables which monitor changes and insert records into the light-weight message table. I’ve always (99% of the time) been of the mindset that database triggers are bad news (Are database triggers evil?). And I would personally much rather develop and debug C# than a SQL trigger.
So, in the pursuit of alternatives, I’ve come across Using SqlDependency to Monitor Database Changes which discusses using the SqlDependency class to detect changes. A quick proof of concept seems to work; however, after looking at several code samples, it looks like with each change that’s detected, new SqlConnection, SqlCommand, and SqlDependency objects will have to be reinitialized and I will probably need 3 or 4 queries that will need to be monitored.
Are there better options to detecting changes to SQL tables in C#?
Also, trigger bias aside, this seems like round-about way to simply monitor changes in one set of tables just to re-insert data into another table. There will be some other logic that will need to take place that I would rather implement in C#, but should I just write triggers to do this and be done with it?
Thoughts?
I think your bias against triggers in general is unfounded. People look down upon triggers for the same reason they look down on cursors: in many cases, they are misused and abused. But like a lot of things they certainly have their place and, when used correctly, are the right answer.
There are some other native technologies you should look into:
Change Tracking
http://msdn.microsoft.com/en-us/library/cc280462(SQL.100).aspx
Change Data Capture
http://msdn.microsoft.com/en-us/library/bb522489(SQL.100).aspx
SQL Server Audit
http://msdn.microsoft.com/en-us/library/cc280386(SQL.100).aspx
Though I don't know your edition (some of these are Enterprise features). Some 3rd party solutions exist as well (I haven't used any so I'll leave it up to you to search / research).

Synchronizing Entire Databases using Microsoft Sync Framework 2.1

I need the ability to sync multiple remote databases, upload and download, with my main database.
However, the problem lies in the fact that I need to sync the entire database, and the database schema is going to be being updated constantly, and I didn't see any way to code it to grab the entire database schema without adding each individual table to the SyncScope.
This is problematic as that scope will always be changing. I solved the initial problem of removing the existing scope, and adding a new one, but I still cannot find any simple solutions, without querying system tables, and parsing the results, and passing those results (for 150+) tables back to my SyncScope.
The reasons I originally looked at Sync Framework are:
I need to be able to manage the direction of the sync (upload/download) when I do a sync programatically from C# on a button click.
I need the ability to turn on that button, based off their network connectivity.
There's additional tasks that need to be done on a sync download, such as changing connection strings of the mobile units, and storing information about their connection and unit in the database.
There's additional tasks that need to be run on a sync upload, such as verifying data against customer business rules through my OR/M, archiving the data to a network storage, restarting the application, and changing connection strings again.
Eventually, I need partial data sets, decided/chosen by the customer, at run-time, at the object level, in an OR/M framework. These objects, may coincide with one or more tables I won't know of at design-time, or may not even exist at design-time.
Does anyone know if another framework encompasses all my requirements, or if there is a simpler way to do this in the sync framework?
For this task, especially with a changing schema, you could consider Merge Replication instead of the Sync framework.

Allowing SQL queries that view data not modify it

I am working on an application that will allow users to create queries on their own to view data in their database. However the stipulation is that the application should prevent any modification of the tables and data stored in the database. The Application will be written in C#. Any good suggestions of how this could be done? Possible idea that I have thought of:
Parse SQL to filter for any reserve word that may alter data(i.e. insert, alter, ect)
There maybe a setting that may prevent modification from this applications connection.
Any suggestion to block any changes made from this application to prevent any chance of a user error or attempt to modify tables of data is much appreciated.
You should run your queries as a user that doesn't have write permission.
Any decent DBMS should have these protections already built in (at a per-user level). You just make sure the only access they have is read-only.
Then you don't have to worry about anything that they do. Let them try to insert, update and delete all they want.
It's a basic tenet of databases that they are responsible for their own security and integrity. You never leave that up to an external application since any monkey can write an application to connect to the database that doesn't follow the rules.
This needs to be handled at the user level rather than the query level. When you set up your app, you'll need to make sure that the account used to run the queries does not have any dbwriter permissions.
This is usually handled by giving users access to (non-updatable) views, but not to tables.
IMHO, the best way is to create a user that can only do select on specified tables. And then use that user for connection.

Categories