开发者

Prevent insert after new Linq-to-SQL object was instantiated

In my application I instantiate a new Linq-to-SQL object and pass it (with some value assigned) to a WinForms window so the user can fill out the rest.

If the user cancels the form I don't want the data to be inserted.

The problem is that when SubmitChanges is called the next time, the record is still inserted.

Is there an easy way to prevent that? I don't want to create a separate class with the same fields as the Linq-to-SQL class when I already have all the fields I need.

I found this article http://www.codeproject.com/KB/linq/linq-to-sql-detach.aspx, but it seems to solve a different problem and doesn't seem like an easy solution.

Update: I was able to reproduce the behavior in a console app. Here is the code I used (with different names like Customer an开发者_开发百科d Country):

MyDatabase db = new MyDataBase(@"Data Source:d:\test.sdf");
Customer customer = new Customer();
customer.Name = "customer 1";
customer.Country = db.Country.FirstOrDefault();

db.SubmitChanges();

The insert happened as soon as I added the "Country" assigment line. Country data in this example is stored in a different table.


The record won't be inserted unless you either call InsertOnSubmit, or it is otherwise attached to your datacontext.

Are you inserting it to your database before you send it to the form? I assume that if your user cancels the form then the object is thrown away?

Perhaps you could post some code, specifically around where you create the object.

edit: it appears that your customer is being attached to the datacontext when you assign it the db.Country.FirstOrDefault(). These EntityRef / EntitySet relationships are two way - when you assign customer.Country = db.Country.FirstOrDefault() you are also effectively saying db.Country.FirstOrDefault().Customers.Add(customer), which adds the customer to the datacontext as a new object. Then when you call SubmitChanges, the customer will be inserted.

The best approach is to either (a) keep the customer detached from the Country until you go to submit then record, or (b) to dispose of the datacontext if the user cancels / fails to submit - and then instantiate a new context. These approaches will definitely work and are a better pattern than you currently have.

However an even simpler way to fix the problem - without any code changes - might be to change the properties of the relationship in the LINQ-to-SQL designer. This is a workaround for your immediate problem, it's not a real fix for the underlying issue of keeping the datacontext around - it's likely you'll run into more problems. However give it a go because it's a very simple fix.

  • Open the dbml in Visual Studio
  • Select the relationship between Customer and Country, and then view Properties
  • You'll see a property for the Child and Parent of the relationship. In the Child section you want to set 'ChildProperty' (or it might be 'IsChildProperty') to false.

Doing this removes the Customers property on the Country object, and will mean that you can set the country in the manner that you are doing without any side-effects; i.e. it won't implicitly associate the Customer with the Country. It means that the Country object no longer 'has' Customers, and so you can't accidentally attach a Customer to a Country. Let me know if this works for you!


when the user cancels the form you can dispose the datacontext object. when the user open the form again you instantiate a new datacontext.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜