none
Why "SubmitChanges" doesn't work properly? RRS feed

  • Question

  • Hi everyone here:)

    A strange question but a little longer passage, please read it carefully, it's a little puzzling;)

    【My database SQL2012】

    【My LINQ-TO-SQL Entity mapping】

    In order to do cascading deleting instead of setting that property in db in SQL management studio, I did this:

    namespace CSharp
    {
    	public partial class MyDbContextDataContext
    	{
    		partial void Deletetb_Category(tb_Category instance)
    		{
    			using (MyDbContextDataContext d = new MyDbContextDataContext())
    			{
    				var r = d.tb_Products.Where(p => p.cid == instance.Id);
    				foreach (var item in r)
    				{
    					d.tb_Products.DeleteOnSubmit(item);
    				}
    				d.SubmitChanges();
    			}
    		}
    		
    	}
     
    	public class MainTest
    	{
    		static void Main(string[] args)
    		{
    			using (MyDbContextDataContext dc = new MyDbContextDataContext())
    			{
    				var result = dc.tb_Categories.First();
    				dc.tb_Categories.DeleteOnSubmit(result);
    				dc.SubmitChanges();
    				Console.WriteLine("OK");
    			}
    		}
    	}
    }

    The problem is that if I comment "Deletetb_Category", the Category will be deleted, but it will raise the problem of ForeignKey_Concurrency. So I handle the partial function to delete all the sub things before delete the Category. VERY STRANGE——The Category won't be deleted at all!

    So I guess "dc.SubmitChanges();" will execute the partial function, and if I don't write that, it will execute to the category and delete itself!

    Am I right? Please tell me kindly about the usages of Delete_Category partial class's execution time (after SubmitChanges()?)

    Please, many thanks!!!!!!!!!!


    我的博客园
    慈善点击,点击此处
    和谐拯救危机,全集下载,净化人心

    Thursday, November 15, 2012 5:59 AM

All replies

  • Hello……

    Well, I found the answer, but I don't know why?

    namespace CSharp
    {
        public partial class MyDbContextDataContext
        {
            partial void Deletetb_Category(tb_Category instance)
            {
                using (MyDbContextDataContext d = new MyDbContextDataContext())
                {
                    var r = d.tb_Products.Where(p => p.cid == instance.Id);
                    
                    foreach (var item in r)
                    {
                        d.tb_Products.DeleteOnSubmit(item);
                        //d.ExecuteDynamicDelete(item);
                    }
                    d.SubmitChanges();
                    ExecuteDynamicDelete(instance);
                }
            }
     
        }
     
        public class MainTest
        {
            static void Main(string[] args)
            {
                using (MyDbContextDataContext dc = new MyDbContextDataContext())
                {
                    var result = dc.tb_Categories.First();
                    dc.tb_Categories.DeleteOnSubmit(result);
                    dc.SubmitChanges();
                }
     
                Console.WriteLine("OK");
     
            }
    
        }
    }

    What's the underlined function? Where's it used? What relationship does it have with SubmitChanges?


    我的博客园
    慈善点击,点击此处
    和谐拯救危机,全集下载,净化人心

    Thursday, November 15, 2012 8:20 AM
  • If you open MyDbDataContext.designer.cs you'll see region Extensibility Method Definitions,where you can find your Deletetb_Category method declaration.

    Also if you take a look at this thread.

    http://social.msdn.microsoft.com/Forums/en/linqtosql/thread/ef7198cf-61b0-4d9c-bcce-0d397c5b76b0

    You'll see that this MSFT guy, explains purpose of Extensibility Methods


    Please mark as reply if helped.
    Also visit my blog http://msguy.net/

    Thursday, November 15, 2012 8:49 AM
  • Hello

    @If you open MyDbDataContext.designer.cs you'll see region Extensibility Method Definitions,where you can find your Deletetb_Category method declaration.

    I know that,THANKS; but what I wanna know is:

    1) When to execute Deletetb_Category? In the SubmitChanges()? or……? I cannot see where it is in the Reflection, but when I debug to see, I found it should be executed when calling SubmitChanges().

    2) Why my first code doesn't work? but 2nd one can?

    3) What's the underlined function of my 2nd reply? Where's it used? What relationship does it have with SubmitChanges?


    我的博客园
    慈善点击,点击此处
    和谐拯救危机,全集下载,净化人心

    Thursday, November 15, 2012 9:00 AM
  • From the example, that I've reproduced right know, I could understand that extensibility methods are purposed for entity validation before sending them to DB. Looks like it overrides default SubmitChanges() functionality.

    But basically I don't prefer to use database table objects with linq, I look at this as a bad practice. If you are interested in how do I see the best practices please review my blog post about LINQ to SQL

    http://msguy.net/post/2012/03/20/LINQ-to-SQL-Practices-and-approaches.aspx


    Please mark as reply if helped.
    Also visit my blog http://msguy.net/

    Thursday, November 15, 2012 9:08 AM
  • @Looks like it overrides default SubmitChanges() functionality.

    yes, I guess so…… But this is a partial function instead of a virtual one. I feel very strange:

    If I complete the partial function, the original function of SubmitChanges won't work properly, as I described above.

    If I didn't complete that, it works well (if you comment my comment function), Why?How does it work?I cannot see through the reflection.

    And what's more!——If I use DynamicExecuteUpdate, it works well again!

    Puzzling……


    我的博客园
    慈善点击,点击此处
    和谐拯救危机,全集下载,净化人心

    Thursday, November 15, 2012 9:11 AM
  • yes I've reproduced both case scenarios. I could only suppose that submitchanges() method looks for the body of extensibility method and if it finds it default functionality is ovverriden by this method

    Please mark as reply if helped.
    Also visit my blog http://msguy.net/

    Thursday, November 15, 2012 9:43 AM
  • MANY thanks Michael,

    Hope Microsoft senior men to explain for us to enhance our knowledge.


    我的博客园
    慈善点击,点击此处
    和谐拯救危机,全集下载,净化人心

    Friday, November 16, 2012 2:06 AM
  • Do this if you are using Entity Framework 4.1 and above

    public void DeleteProduct(int productid, Product product)

    {

      //Create a data context

      CommerceEntities context = new CommerceEntities();

      //Retrieve a row by id

      Product delproduct = context.Products.First(p => p.ProductID == productid);

      //Sent the deletion

      context.Products.Remove(delproduct);

      //Commit delete

      context.SaveChanges();

    }

    chanmm


    chanmm

    Friday, November 16, 2012 7:25 AM
  • Hi chanm;)

    I'm using LINQ-TO-SQL, but still thanks u all the same.

    Hope a senior man can offer us answers;)


    我的博客园
    慈善点击,点击此处
    和谐拯救危机,全集下载,净化人心

    Friday, November 16, 2012 10:33 AM
  • Hi 编程志愿者,

    Welcome to the MSDN forum.

    You are right. If you implement the Insert, Update and Delete methods in your partial class, the LINQ to SQL runtime will call them instead of its own default methods when SubmitChanges is called. This enables you to override the default behavior for create / read / update / delete operations. It means if you only delete all the orphans of an instance in your original code, the instance still exists. Please check this page: http://msdn.microsoft.com/en-us/library/bb882671.aspx

    The DataContext.ExecuteDynamicDelete Method executes, inside delete override methods, to redelegate to LINQ to SQL the task of generating and executing dynamic SQL for delete operations. In this way, the default delete method is executed, so the father instance is deleted later. Please check this page: http://msdn.microsoft.com/en-us/library/system.data.linq.datacontext.executedynamicdelete.aspx

    Best Regards,


    Alexander Sun [MSFT]
    MSDN Community Support | Feedback to us

    Monday, November 19, 2012 8:33 AM
  • Hello Alexander Sun:)

    First many thanks for your GREAT reply!

    @If you implement the Insert, Update and Delete methods in your partial class, the LINQ to SQL runtime will call them instead of its own default methods when SubmitChanges is called.

    I feel very curious at what you say——U mean if I implement the partial function, it will call my logic codes instead of the default given one, so where my partial function is called? I cannot find that anywhere by reflecting tools:( And the codes are:

    public virtual void SubmitChanges(ConflictMode failureMode)
    {
        this.CheckDispose();
        this.CheckNotInSubmitChanges();
        this.VerifyTrackingEnabled();
        this.conflicts.Clear();
        try
        {
            this.isInSubmitChanges = true;
            if (!(Transaction.Current == null) || this.provider.Transaction != null)
            {
                (new ChangeProcessor(this.services, this)).SubmitChanges(failureMode);
                this.AcceptChanges();
            }
            else
            {
                bool flag = false;
                DbTransaction dbTransaction = null;
                try
                {
                    try
                    {
                        if (this.provider.Connection.State == ConnectionState.Open)
                        {
                            this.provider.ClearConnection();
                        }
                        if (this.provider.Connection.State == ConnectionState.Closed)
                        {
                            this.provider.Connection.Open();
                            flag = true;
                        }
                        dbTransaction = this.provider.Connection.BeginTransaction(IsolationLevel.ReadCommitted);
                        this.provider.Transaction = dbTransaction;
                        (new ChangeProcessor(this.services, this)).SubmitChanges(failureMode);
                        this.AcceptChanges();
                        this.provider.ClearConnection();
                        dbTransaction.Commit();
                    }
                    catch
                    {
                        if (dbTransaction != null)
                        {
                            dbTransaction.Rollback();
                        }
                        throw;
                    }
                }
                finally
                {
                    this.provider.Transaction = null;
                    if (flag)
                    {
                        this.provider.Connection.Close();
                    }
                }
            }
        }
        finally
        {
            this.isInSubmitChanges = false;
        }
    }

    So from the given codes you see it that this is a base class that can be inherited by any other sub classes generated from the given existing db tables, and I CANNOT see where the partial function is called, what's more, even if there's someplace calling the partial method, how can a father class knows the sub inherited class's partial methods?

    Thanks for watching the issue. Hope your reply again and I'M VERY GLAD TO TALK TO YOU TO SAY SOMETHING ABOUT THE DEEP QUESTION ISSUE.


    我的博客园
    慈善点击,点击此处
    和谐拯救危机,全集下载,净化人心

    Monday, November 19, 2012 8:55 AM
  • Hi 编程志愿者,

    I mean this extensibility method Deletetb_Category in your class MyDbContextDataContext.

    Best Regards,


    Alexander Sun [MSFT]
    MSDN Community Support | Feedback to us


    Tuesday, November 20, 2012 6:56 AM
  • Hello again MSFT;)

    Thanks for so much patient!

    Then I should clearify my problem starting from partial method——

    Like partial class, this partial method will be merged during compiling instead of running, so it's QUITE DIFFERENT FROM virtual-override. There comes an example:

    【Sample 1:To call a partial method that isn't implemented】

    namespace CSharp
    {
        public partial class PartialClassTest
        {
            partial void PartialMethodTest();
            public PartialClassTest()
            {
                PartialMethodTest();
            }
        }
     
        public class MainTest
        {
            static void Main(string[] args)
            {
                PartialClassTest pc = new PartialClassTest();
            }
        }
    }

    The IL should be this:

    .class public auto ansi beforefieldinit CSharp.PartialClassTest
        extends [mscorlib]System.Object
    {
        .method public hidebysig specialname rtspecialname 
            instance void .ctor () cil managed 
        {
            IL_0000: ldarg.0
            IL_0001: call instance void [mscorlib]System.Object::.ctor()
            IL_0006: nop
            IL_0007: nop
            IL_0008: nop
            IL_0009: ret
        }
    }

    【Sample 2:To call a partial method that has been implemented】

    namespace CSharp
    {
        public partial class PartialClassTest
        {
             partial void PartialMethodTest();
            public PartialClassTest()
            {
                //调用这个部分方法!
                PartialMethodTest();
            }
        }
     
        public partial class PartialClassTest
        {
            partial void PartialMethodTest()
            {
                Console.WriteLine("实现了这个部分方法!");
            }
        }
        public class MainTest
        {
            static void Main(string[] args)
            {
                PartialClassTest pc = new PartialClassTest();
            }
        }
    }

    The IL should be:

    .class public auto ansi beforefieldinit CSharp.PartialClassTest extends [mscorlib]System.Object { .method public hidebysig specialname rtspecialname instance void .ctor () cil managed { IL_0000: ldarg.0 IL_0001: call instance void [mscorlib]System.Object::.ctor() IL_0006: nop IL_0007: nop IL_0008: ldarg.0 IL_0009: call instance void CSharp.PartialClassTest::PartialMethodTest() IL_000e: nop IL_000f: nop IL_0010: ret } .method private hidebysig instance void PartialMethodTest () cil managed { IL_0000: nop IL_0001: ldstr "实现了这个部分方法!" IL_0006: call void [mscorlib]System.Console::WriteLine(string) IL_000b: nop IL_000c: ret } }

    Now you can see that even if I wanna use the partial method in the PartialClassTest, it should be included and called inside the PartialClassTest itself!This is ONLY A SIMPLE SAMPLE TO PROVE THAT PARTIAL METHOD SHOULD BE ALSO CALLED.

    Now turn to my original question:Where's Deletetb_Category called?I ONLY define that without seeing it's used anywhere in the DataContext or in the sub class?

    And even if it's used in SubClass, how to notify its parent class to know the sub class's partial method's defination?I cannot see anything here in the reflector!

    :(


    我的博客园
    慈善点击,点击此处
    和谐拯救危机,全集下载,净化人心

    Tuesday, November 20, 2012 7:25 AM
  • @Alexander Sun [MSFT]

    Can u help me with that a good explaination……:(

    I really don't understand……


    我的博客园
    慈善点击,点击此处
    和谐拯救危机,全集下载,净化人心

    Thursday, November 22, 2012 9:20 AM
  • Hi,

    I am trying to involve another senior expert in your thread. Please wait the response. Sorry for any inconvenience.


    Alexander Sun [MSFT]
    MSDN Community Support | Feedback to us

    Friday, November 23, 2012 7:49 AM
  • Hi,

    I am trying to involve another senior expert in your thread. Please wait the response. Sorry for any inconvenience.


    OK, many thanks……waiting for ur reply;)

    我的博客园
    慈善点击,点击此处
    和谐拯救危机,全集下载,净化人心

    Friday, November 23, 2012 7:52 AM
  • Hi,

    Have you done any live debugging to step through the scenarios? Are you not seeing the expected code path?

    Thanks,

    Cathy Miller

    Thursday, November 29, 2012 4:05 PM
    Moderator
  • Hello Cathy again:)

    My codes run well, but I only wanna know the reason why? Please have a clear look at my above posts;)


    我的博客园
    慈善点击,点击此处
    和谐拯救危机,全集下载,净化人心
    想更多交流?请点击此处……

    Friday, November 30, 2012 1:35 AM
  • Hi,

    From a support perspective this is really beyond what we can do here in the forums. If you cannot determine your answer here or on your own, consider opening a Advisory Services case with us. Visit this link to see the various support options that are available to better meet your needs:  http://support.microsoft.com/default.aspx?id=fh;en-us;offerprophone.

    Thanks,

    Cathy

    Monday, December 10, 2012 4:11 PM
    Moderator
  • Still waiting for the answer, I don't know——Since this is produced by Microsoft, why cannot I get the answer so quickly?

    Don't you have codes or codes are secreat?

    Cathy Miller?


    我的博客园
    慈善点击,点击此处
    和谐拯救危机,全集下载,净化人心


    Tuesday, December 11, 2012 4:32 AM