having trouble with delete

Jul 16, 2009 at 5:52 PM

Mike (or anyone) --

Please help.

I am having trouble with delete.

I think it is a syntax issue on my part.

Below is my code.

What do you think?


 /// <summary>
 /// This is int "ProcessingRecord_Test" and this will execute a test for deletion.
 /// </summary>
 [Test]
 public void DeleteTest01()
 {
  System.DateTime methodStartTime = System.DateTime.Now;

  //For now, just hardcode a known, existing record ID here for a simple test...
  long myPkId1 = 494;

  //Test Delete.
  Business.Entities.WorkProcessingRecordManager myProcessingRecordManager1 = new Business.Entities.WorkProcessingRecordManager();

  //This is the call that fails.
  myProcessingRecordManager1.Delete(myPkId1);

  System.TimeSpan methodDuration = System.DateTime.Now.Subtract(methodStartTime);

  System.Console.WriteLine(String.Format(MethodBase.GetCurrentMethod().Name + " Time Elapsed: {0}", methodDuration.ToString()));
 }

 /// <summary>
 /// This is in "ProcessingRecordManager" and this will delete the object with the given ID, if the ID does exist.
 /// </summary>
 /// <param name="targetPkId">This is the ID to use.</param>
 /// <remarks>
 /// If the ID does not exist, then this will not throw an exception and will not make any changes.
 /// </remarks>
 public void Delete(object targetPkId)
 {
  ArrayList myPkIdList = new ArrayList();
  myPkIdList.Add(targetPkId);

  //Call an overload.
  this.Delete(myPkIdList);
 }

 /// <summary>
 /// This is in "ProcessingRecordManager" and this will loop and this will delete the object with the given ID, if the ID does exist.
 /// </summary>
 /// <param name="targetPkIdList">This is the list of IDs to use.</param>
 /// <remarks>
 /// If the ID does not exist, then this will not throw an exception and will not make any changes.
 /// </remarks>
 public void Delete(ArrayList targetPkIdList)
 {
  if (targetPkIdList == null)
  {
   throw new System.ApplicationException("The given object, targetPkIdList, is null.");
  }
  else
  {
   //Continue.
  }

  using (Business.Entities.DataClassesContext myContext =
   new Business.Entities.DataClassesContext(Business.Components.EntityHelper.GetConnectionString()))
  {
   myContext.DeferredLoadingEnabled = false;
   long myPkIdTemp = long.MinValue;
   IEnumerator myEnumerator = targetPkIdList.GetEnumerator();
   myEnumerator.Reset();
   Business.Entities.WorkProcessingRecord myEntityTemp = null;

   while (myEnumerator.MoveNext())
   {
    myPkIdTemp = Convert.ToInt64(myEnumerator.Current);

    var q = from p in myContext.WorkProcessingRecords
            where (p.Id == myPkIdTemp)
            select p;

    if ((q == null) || (q.LongCount() <= 0L) || (q.First() == null))
    {
     //Continue. The given ID does not exist.
    }
    else if (q.LongCount() == 1L)
    {
     //Test01. If one tries this...
     //
     //myEntityTemp = (Business.Entities.WorkProcessingRecord)(q.First());
     //myEntityTemp.SetAsChangeTrackingRoot(EntityState.Deleted);
     //myEntityTemp.SynchroniseWithDataContext(myContext);
     //myContext.SubmitChanges();
     //
     //...then one gets the RTE of  "Cannot attach an entity that already exists"...
     //...on the "SynchroniseWithDataContext" line.

     //Test02: If one tries this...
     //
     //myEntityTemp = (Business.Entities.WorkProcessingRecord)(q.First());
     //myEntityTemp.SetAsChangeTrackingRoot(EntityState.Original);
     //myEntityTemp.SetAsDeleteOnSubmit();
     //myEntityTemp.SynchroniseWithDataContext(myContext);
     //myContext.SubmitChanges();
     //
     //...then one gets a RTE of "Cannot attach an entity that already exists"...
     //...on the "SynchroniseWithDataContext" line.

     //Test03. If one tries this...
     //
     //myEntityTemp = (Business.Entities.WorkProcessingRecord)(q.First());
     //myEntityTemp.SetAsDeleteOnSubmit();
     //myEntityTemp.SynchroniseWithDataContext(myContext);
     //myContext.SubmitChanges();
     //
     //...then one gets a RTE of "You cannot change the Entity State when the Entity is not change tracked"...
     //...on the "SetAsDeleteOnSubmit: line.

     //Test04. If one tries this...
     //
     myEntityTemp = (Business.Entities.WorkProcessingRecord)(q.First());
     myEntityTemp.SetAsChangeTrackingRoot(EntityState.Deleted);
     myEntityTemp.SetAsDeleteOnSubmit();
     myEntityTemp.SynchroniseWithDataContext(myContext);
     myContext.SubmitChanges();
     //
     //...then one gets a RTE of "Cannot attach an entity that already exists"...
     //...on the "SynchroniseWithDataContext" line.
    }
    else
    {
        throw new System.ApplicationException("A retrieve for myPkIdTemp='" + myPkIdTemp.ToString() + "' returned LongCount='" + q.LongCount().ToString() + "'.");
    }
   }
  }
 }

 

Please advise.

Thank you.

-- Mark Kamoski

Coordinator
Jul 16, 2009 at 10:31 PM
Edited Jul 16, 2009 at 10:33 PM

Hi again Mark,

The issue is that when you do the operation in the same data context as the retrieval of the information it is already attached to that data context and hence it fails.  You are not disconnecting between the two operations of retrieving the data and updating the data, but you are using the disconnected functionality.

Basically, to do what you want you have these options:

1) don't use SyncroniseWithDataContext() or SetAsChangeTrackingRoot(), instead just do myContext.DeleteOnSubmit(xxx) which is the connected way of doing it when the object is already attached.

2) Disconnect the object by using a different data context

Example:

using(dc ....)

{

.... retrieve data

}

using(dc ....)

{

.... update data

}

Option 1 above is what you want though, because u don't need the "disconnected" functionality to do this.

I might have a look on the weekend to see if I can make it work in both situations (connected/disconnected).

Cheers

Matt

Jul 17, 2009 at 12:10 PM
Edited Jul 17, 2009 at 12:18 PM

Mike --

Regarding this...

>>>1) don't use SyncroniseWithDataContext() or SetAsChangeTrackingRoot(), instead just do myContext.DeleteOnSubmit(xxx) which is the connected way of doing it when the object is already attached.... is what you want though, because u don't need the "disconnected" functionality to do this.

...that is exactly what I thought.

Below is how I am handling delete now and it seems fine.

What do you think?

 

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Team.Clear.Business.Entities
{
	class testClass1
	{
		/// <summary>
		/// This will delete the entity with the given ID if the ID does exist.
		/// </summary>
		/// <param name="targetPkId">This is the ID to use.</param>
		/// <remarks>
		/// If the ID does not exist, then this will NOT throw an exception and will NOT make any changes.
		/// </remarks>
		public void Delete(object targetPkId)
		{
			if (targetPkId == null)
			{
				throw new System.ApplicationException("The given object, targetPkId, is null.");
			}
			else
			{
				//Continue.
			}

			ArrayList myPkIdList = new ArrayList();
			myPkIdList.Add(targetPkId);

			//Call an overload.
			this.Delete(myPkIdList);
		}

		/// <summary>
		/// This will interate the given list and will delete the entity with the given ID if the ID does exist.
		/// </summary>
		/// <param name="targetPkIdList">This is the list of IDs to use.</param>
		/// <remarks>
		/// If the ID does not exist, then this will NOT throw an exception and will NOT make any changes.
		/// </remarks>
		public void Delete(ArrayList targetPkIdList)
		{
			if (targetPkIdList == null)
			{
				throw new System.ApplicationException("The given object, targetPkIdList, is null.");
			}
			else
			{
				//Continue.
			}

			using (Team.Clear.Business.Entities.DataClassesContext myContext =
				new Team.Clear.Business.Entities.DataClassesContext(Business.Components.EntityHelper.GetConnectionString()))
			{
				myContext.ObjectTrackingEnabled = Team.Clear.Common.Core.Consts.DefaultObjectTrackingEnabledFlag;
				myContext.DeferredLoadingEnabled = myContext.ObjectTrackingEnabled;

				//NOTE. public const bool DefaultObjectTrackingEnabledFlag = true;

				long myPkIdTemp = long.MinValue;
				IEnumerator myEnumerator = targetPkIdList.GetEnumerator();
				myEnumerator.Reset();

				while (myEnumerator.MoveNext())
				{
					//FailFast if conversion is not valid.
					myPkIdTemp = Convert.ToInt64(myEnumerator.Current);

					var q = from n in myContext.WorkProcessingRecords
							where (n.Id == myPkIdTemp)
							select n;

					if ((q == null) || (q.LongCount() <= 0L) || (q.First() == null))
					{
						//Continue. The ID does not exist.
					}
					else if (q.LongCount() == 1L)
					{
						myContext.WorkProcessingRecords.DeleteOnSubmit(q.First());
						myContext.SubmitChanges(Team.Clear.Common.Core.Consts.DefaultConflictMode);

						//NOTE. public const System.Data.Linq.ConflictMode DefaultConflictMode = System.Data.Linq.ConflictMode.FailOnFirstConflict;
					}
					else
					{
						throw new System.ApplicationException("A retrieve for myPkIdTemp='" + myPkIdTemp.ToString() + "' returned LongCount='" + q.LongCount().ToString() + "'.");
					}
				}
			}
		}

	}
}

Please advise.
Thank you.
-- Mark Kamoski
Coordinator
Jul 17, 2009 at 7:16 PM

Hi Mark,

Yep, that's pretty much it :)

Cheers

Matt.