none
basic question to use the ChangeTracker.ChangeTrackingEnabled in STE RRS feed

  • Question

  • Hello

    my first project with Self-Tracking-Entities in Entity-Framework, and i have the first question -> What exactly is the purpose of the "ChangeTrackingEnabled"-property. I have some test-methods, to create or modify an entity and save this back to database. This works with both options - ChangeTrackingEnabled = true;, or with ChangeTrackingEnabled = false;

    For example a create-new-script:

    private static int CreateNewAufnahmeArt()
    {
          using (AufnahmeArtenRepository aufArtRepo = new AufnahmeArtenRepository())
          {
            Aufnahmeart newAufnahmeArt = new Aufnahmeart();
            newAufnahmeArt.Aktiv = true;
            newAufnahmeArt.Bezeichnung = "test-77777";
            //newAufnahmeArt.ChangeTracker.ChangeTrackingEnabled = true;
            aufArtRepo.Save(newAufnahmeArt);
            return newAufnahmeArt.PrimaryKey;
          }
    }
    

    or for example a modify-script:

    private static void ModifyAufnahme(int primKey)
    {
          using (AufnahmeArtenRepository aufArtRepo = new AufnahmeArtenRepository())
          {
            // Retieve the data: (the second parameter is for the ChangeTrackingEnabled)
            var found = aufArtRepo.RetrieveByPrimaryKey(primKey, false);
            found.Bezeichnung = "Änderung 1243";
            aufArtRepo.Save();
          }
    }
    

    Is this only possible, if i work with original-values in my Self-Tracking-Entities-Framework??

    Please, can here some professionals help me, or have some information to this theme for me ?

    Many thanks in advance

    Hans



    Monday, July 4, 2011 1:51 PM

Answers

  • For your first question. As long that you don't return your list for further treatment outside your context, you never need to either start tracking or mark it as modified. BUT, if you fetch the records, changes them and you don't save the changes to the storage, you need to start tracking before modifying them. This is because when you finally what to store your changes you need to apply them to a new objectcontext, and then the changetracker is required so STE knows which changes to add to the ObjectContext's statemanager. If you never want to store the changes at all, you never need to start tracking at all.. Tracking is ONLY needed if:

    1. You make changes to the entities OUTSIDE the ObjectContext

    2. You need to store the changes in entities if the entities has been modified outside the lifetime of the ObjectContext that created them.

     

    As for your second question. Again, this is connected a bit to answer 1. If your ObjectContext lives the whole time your entities is used, you never need STE, STE is ONLY useful if you disposes the ObjectContext that created the entities and you want to reattach them to a another ObjectContext later.

    To take your WinForms project as an example. If you have your ObjectContext (or a DataLayer that maintains a ObjectContext as long as it lives) as a member variable of your WinForm, you don't need STE, since the ObjectContext will live as long as your WinForm is not disposed. HOWEVER, if you create a local instance of the ObjectContext/DataLayer when you retrieve the data you want to display, disposes the ObjectContext/DataLayer and disposes it, and then the user works with the entities and on when the user saves you create a new ObjectContext/DataLayer instance, then you need tracking functionality like STE, and your fetch code need to call StartTracking() before the user begins modifying data.


    --Rune
    • Marked as answer by Hans Tausch Friday, July 8, 2011 5:51 PM
    Friday, July 8, 2011 8:37 AM

All replies

  • Hello,

    it is hard to answer your question because you are asking question about EF and in the same time you are hiding all related EF code in some repository. The code you posted is mostly unrelated to the question you are asking.

    But generally STE has its own change tracker and its change tracking is not turned on by default. Attached STE is still tracked by the context so if your repository uses the same context instance for loading entity and saving entity and there is no serialization / detaching involved, it is tracked by the context itself and its self tracking features are not used.

    Best regards,
    Ladislav

    Monday, July 4, 2011 2:52 PM
  • Hello Ladislav

    Thanks for your reply!!

    I have in my repository-classes a baseRepository which handles the context (and other base-methods):

    public abstract class BaseRepository<TEntity, IdentityKey> : IDisposable, IBaseRepository, IBaseRepository<TEntity> where TEntity : BaseEntity<IdentityKey>, IBaseEntity<IdentityKey>, IObjectWithChangeTracker
      {
    
        private static object _sync = new object();
        private PhysioEntities _ObjectContext;
        protected PhysioEntities ObjectContext
        {
          get
          {
            lock (_sync)
            {
              if (_ObjectContext == null)
              {
                _ObjectContext = new PhysioEntities(PhysioConnection.PhysioConnectionStringBuilder.ConnectionString);
                _ObjectContext.ContextOptions.LazyLoadingEnabled = false;
              }
            }
    
            return _ObjectContext;
          }
        }
    ...
    ....
    ......
    
    And in a derived specific-class, i have for example the "GetBaseQuery()"-method, that i'm using in the Retrieve-method:

     

     

    public class AufnahmeArtenRepository : BaseRepository<Aufnahmeart, int>
    {
        protected override ObjectSet<Aufnahmeart> GetBaseQuery()
        {
          return ObjectContext.Aufnahmearten;
        }
    
        public IEnumerable<Aufnahmeart> RetrieveByActive(bool active, bool changeTrackingEnabled=false)
        {
          var list = (from p in this.GetBaseQuery()
                   where
                     p.Aktiv == active
                   select p).ToList();
          if (list != null)
            SetChangeTrackingEnabled(list, changeTrackingEnabled);
          return list;
        }
    ....
    .....
    .......
    
    

    Now i use this specific context-class in a "using"-statement - do a retrieve, change the data and save this back to database (like the code-example in my first thread), i think it is always the same context. So i could provide always the "ChangeTracker" to false  - or is this not correct?

    And when are the features for self tracking used ??

     

    Thanks for any information & best regards

     


    Hans Tausch
    Monday, July 4, 2011 6:38 PM
  • Hi,

    Self-Tracking Entities is primarly for N-Tier applications where you pass entities via the wire with for example WCF. STE is designed to change track disconnected entities (that is entities outside a valid context), so that when they are passed back to the serverside, they can be attached back to the context and changes of the entities is added to the ObjectContext.ObjectStateManager using the ApplyChanges extension function.

    The technology of STE starts the tracking of the entities whenever an entity is deserialized on either side of a WCF endpoint, or you can start the tracking functionality using the StartTracking function.

    For more information about STE refer to this link: http://msdn.microsoft.com/en-us/library/ff407090.aspx

     


    --Rune
    Monday, July 4, 2011 8:43 PM
  • Hello

    o.k. - thanks for your feedback - now i understand "basically" this theme.

    But one question - i have tested this in my application. I have an application-mix (some parts in Asp.net, some parts with wcf and some parts are win-forms - and all work with the same dataLayer, and businessLayer). I tested in the win-form-application-part. So i retrieved a list of data from database

      protected override ObjectSet<TerminWarteliste> GetBaseQuery()
      {
       return ObjectContext.TerminWartelisten;
      }
    
      public IEnumerable<TerminWarteliste> RetrieveByFallId(Guid currentPatFallPrimaryKey, bool changeTrackingEnabled = false)
      {
       var list = (from p in this.GetBaseQuery()
          where
           p.PatFall == currentPatFallPrimaryKey
          select p).ToList();
       if (list != null)
        SetChangeTrackingEnabled(list, changeTrackingEnabled);
       return list;
      }
    

     

       and after this, i make a modification:

     

     try
       {
        using (TerminWartelisteRepository twListRepo = new TerminWartelisteRepository())
        {
         // retrieve with changeTrackingEnabled true or false !!!
         var foundList = twListRepo.RetrieveByFallId(primKeyPatFallImPool,true/false);
    
         if (foundList.Count() > 0)
         {
          foreach (var item in foundList)
          {
           // do a modification
           item.PatFall = primKeyPatFallZielBehandlung;
          }
         }
         twListRepo.Save(foundList);
        }
       }
       catch (Exception ex)
       {
        EsClassLibrary.MessageLogging.ShowExceptionMessageBox(ex, "Fehler CopyTerminWarteschlangenEintrag()");
        return EsClassLibrary.ActionReturnCodes.Failure;
       }
    

     

    if i start the retrieve with the "true"-flag for the ChangeTrackingEnabled, the ChangeTracker.State is set to "modified". If i set after the retrieve the ChangeTrackingEnabled to "false", modify a property in my data-list, the ChangeTracker.State is  not changed - it is continue to "unchanged".....

    So, that's the question for me - Must i always work with the ChangeTracker ??? - I have the Statement in the win-Form-application in an "using"-statement, so the ObjectContext is not destroyed between the retrieve of data and the update.

    Or I think here still wrong????

     

    Thanks for your help in advance & best regards


    Hans Tausch
    Friday, July 8, 2011 6:57 AM
  • Hi,

    As long as you work within an active context, you don't need to call StartTracking on an STE entity, the ObjectStateManager of the ObjectContext takes care of it as long as its ObjectContext is active.

    But again, you should really consider if you really needs STE if your code looks like your example.


    --Rune
    Friday, July 8, 2011 8:05 AM
  • hi

    thanks for your reply!!

    You are right, but if i don't StartTracking, change the values of some properties - i have the ChangeTracker.State to "unchanged", and not Update in the database ???

    Must i set "MarkAsModified()" in this example ??

    And why do you think whether I really need STE or should use that in my projekt ?? (If a DataLayer in STE exists, I don't create a own or second dataLayer for the win-Form-Projekt.......??)

    Best regards

     


    Hans Tausch
    Friday, July 8, 2011 8:13 AM
  • For your first question. As long that you don't return your list for further treatment outside your context, you never need to either start tracking or mark it as modified. BUT, if you fetch the records, changes them and you don't save the changes to the storage, you need to start tracking before modifying them. This is because when you finally what to store your changes you need to apply them to a new objectcontext, and then the changetracker is required so STE knows which changes to add to the ObjectContext's statemanager. If you never want to store the changes at all, you never need to start tracking at all.. Tracking is ONLY needed if:

    1. You make changes to the entities OUTSIDE the ObjectContext

    2. You need to store the changes in entities if the entities has been modified outside the lifetime of the ObjectContext that created them.

     

    As for your second question. Again, this is connected a bit to answer 1. If your ObjectContext lives the whole time your entities is used, you never need STE, STE is ONLY useful if you disposes the ObjectContext that created the entities and you want to reattach them to a another ObjectContext later.

    To take your WinForms project as an example. If you have your ObjectContext (or a DataLayer that maintains a ObjectContext as long as it lives) as a member variable of your WinForm, you don't need STE, since the ObjectContext will live as long as your WinForm is not disposed. HOWEVER, if you create a local instance of the ObjectContext/DataLayer when you retrieve the data you want to display, disposes the ObjectContext/DataLayer and disposes it, and then the user works with the entities and on when the user saves you create a new ObjectContext/DataLayer instance, then you need tracking functionality like STE, and your fetch code need to call StartTracking() before the user begins modifying data.


    --Rune
    • Marked as answer by Hans Tausch Friday, July 8, 2011 5:51 PM
    Friday, July 8, 2011 8:37 AM
  • Hello

    Thank you for your help, and the detailed description!!!

    Best regards


    Hans Tausch
    Friday, July 8, 2011 5:51 PM