views:

232

answers:

2

Hi, I am new to LINQToSQL. Is there a way to overwrite the "InsertOnSubmit" or "DeleteOnSubmit" methods of the DataContext class for a particular entity?

Like for example, I have a database table called Customers that has a boolean field "IsDeleted" which holds true if the user deletes a customer record from UI. If I will call the _myDataContext.Customers.DeleteOnSubmit(..), bydefault it will physically delete the record from the table which I don't want. Instead, I want it to be logically deleted by setting the "IsDeleted" field to true.

One way of doing this is to Get the object and call the Update method (instead of Delete) after setting the property value. This will work as well but just out of curiosity, I want to know if the standard DataContext methods (InsertOnSubmit, DeleteOnSubmit etc) are over-writable? And if so, how?

Thanks

A: 

As far as I know, no they are not. If you don't want to delete it... don't call delete! However, some other options:

  • you could map the delete to a stored procedure that just sets the flag at the database
  • you may be able to override SubmitChanges and fix-up any changes (via GetChangetSet) before calling base.SubmitChanges - however, I'm dubious as to whether this is a good idea; it may need re-inserting the item, for example.

Code:

partial class MyDataContext {
    public override void SubmitChanges(ConflictMode failureMode) {
        var delta = GetChangeSet();
        foreach(var record in delta.Deletes.OfType<Customer>()) {
            Customers.InsertOnSubmit(record);
            record.IsDeleted = true;
        }
        base.SubmitChanges(failureMode);
    }
}

Obviously if it needs to be more flexible you may want to use GetTable() (rather than a rigid Customers property).


Updates re your comment; I honestly don't think you can do it at that point; re the "10 places" thing... IMO you should be hiding the data-context behind a repository interface anyway, so all 10 places would be calling a method like CreateUser which deals with the data-context and necessary logic (perhaps with a separate business logic class to handle some of the rules). And further, uniqueness should usually be handled at the database level anyway (via a constraint) due to concurrency concerns.

But to do what you want before trying to save them:

partial class MyDataContext {
    public override void SubmitChanges(ConflictMode failureMode) {
        var delta = GetChangeSet();
        foreach(var record in delta.Inserts.OfType<User>()) {
            if(Users.Any(x=>x.Name == record.Name) {...throw an exception...}
        }
        base.SubmitChanges(failureMode);
    }
}
Marc Gravell
Okay, here is the actual use-case. Please let me know how best this can be achieved. I have a table name users and I want to ensure that the username user is trying adding does not already exists. I can very easily execute a query to check this before calling _DataContext.Users.InsertOnSubmit(objUser) but what if this operation is getting performed from 10 places in my application? I have to add that check at all the 10 places. Instead, if I overwrite the InsertOnSubmit method for DataContext.Users and perform this check before calling base.InsertOnSubmit, I only have to do it at 1 place.
Farhan Zia
There must be someway of doing it this way. This is a very common scenario.
Farhan Zia
I beleive that's what I was missing; a proxy. I was trying avoiding that extra layer from the middle to get the benifits of LINQToSQL objects being bindable but it looks like there are no other options than to hide LinqToSql behind a proxy so that the custom logic can be added.
Farhan Zia
BTW Marc, I tried to rate your reply but I am just too new at StackOverFlow as well so don't have that reputation score yet to do so :) Thanks anyway.
Farhan Zia
No problem - it wouldn't make any difference anyway (I've hit today's rep cap - only green ticks count, and I got that ;-p)
Marc Gravell
A: 

If you want to avoid duplicate usernames in your database, why not put an unique index on this field?

Workshop Alex
I can and actually already have but the scenario I mentioned above was just an example about the question how to handle any custom logic.
Farhan Zia