views:

526

answers:

4

Is there a way to determine if a LINQ object has not yet been inserted in the database (new) or has been changed since the last update (dirty)? I plan on binding my UI to LINQ objects (using WPF) and need it to behave differently depending whether or not the object is already in the database.

MyDataContext context = new MyDataContext();
MyObject obj;
if (new Random().NextDouble() > .5)
    obj = new MyObject();
else
    obj = context.MyObjects.First();
// How can I distinguish these two cases?

The only simple solution I can think of is to set the primary key of new records to a negative value (my PKs are an identity field and will therefore be set to a positive integer on INSERT). This will only work for detecting new records. It also requires identity PKs, and requires control of the code creating the new object.

Is there a better way to do this? It seems like LINQ must be internally tracking the status of these objects so that it can know what to do on context.SubmitChanges(). Is there some way to access that "object status"?

Clarification Apparently my initial question was confusing. I'm not looking for a way to insert or update records. I'm looking for a way, given any LINQ object, to determine if that object has not been inserted (new) or has been changed since its last update (dirty).

+1  A: 

The DataContext object internally tracks changes to the data so it can optimize the SQL queries generated when you call SubmitChanges().

If you want to insert new objects to the database, rather than update existing objects, you should do something like:

MyDataContext context = new MyDataContext();
MyObject obj;
if (new Random().NextDouble() > .5)
{
    obj = new MyObject();
    context.MyObjects.InsertAllOnSubmit(obj);
}
else
    obj = context.MyObjects.First();

Now when you call SubmitChanges(), it will generate both an INSERT and an UPDATE if necessary. Depending on how fast you need a primary key on your new object, you could submit it right away to submit the object, flush the change tracking and get your new primary key.

womp
This isn't quite what I'm looking for. I know how to insert / update using LINQ. What I need is to determine the status of any given LINQ object.
Joseph Sturtevant
+4  A: 

ChangeSet changes = context.GetChangeSet();

If changes.Inserts.Contains(yourObject) then it is new and will be inserted when SubmitChanges is called

If changes.Updates.Contains(yourObject), it's already in the database, and will be updated on SubmitChanges()

Eivind T
+1  A: 

I create a partial class for each object LINQ creates (Data Objects) and have each object Implement IDataObject interface

/// /// This interface is used to implement IsNew in all LINQ objects so a Generic Save method /// can be used. /// public interface IDataObject {

    #region Properties


        #region IsNew
        /// <summary>
        /// Is this a new object
        /// </summary>
        bool IsNew
        {
            get;
        } 
        #endregion


    #endregion

} 
#endregion

In each data object I implement the IsNew Property to return true if the PrimaryKey has been set:

/// /// Is this a new object /// public bool IsNew { get { // initial value bool isNew = (this.CustomerID > 0);

                // return value
                return isNew;
            }
        }

Then in my DataContext I cast the ojbect to be saved as an IDataObject and if it is new I call InsertOnSubmit() before calling SubmitChanges().

This might not be the simplest way but it allows all objects to be saved generically.

It takes a few minutes for each table to implement the Interface but it allows for a Generic Save() method to be called.

A: 

There is INotifyPropertyChanging and INotifyPropertyChanged interfaces that have specific methods to be fired on insertion that is let you know if the object get dirty. If you use SQLMetal, it does it automatically. if you write your own entity classes you have manually write these plumbing staff yourself. But I am not sure if this solution is suitable from scalability point of view. I have not test it. It seems that it might have problems since it fires an event on the machine that does the insertion.

Eddy Mishiyev