0

I created a working solution, which overrides SaveChanges() but would like to know if there is a better, cleaner way to do this. I really don't like the switch statement. Below, I have described the problem and illustrated my full solution.

Thanks

The problem Whenever a user does something that inserts, updates or deletes some of their data, which is spread across multiple tables, update the column NewClub.LastActivityDate = DateTime.Now

The Models

public  class NewClub
{
 //Primary Key
 public int Id { get; set; }
 [...]
 public DateTime  LastActivityDate { get; set; }
}

 public class NewClubProspect
 {
   //Primary Key
   [Key]
   public int Id { get; set; }
   //Foreign Key
   public int NewClubId { get; set; }
   [..]
    public virtual NewClub NewClub { get; set; }
}

 public class NewClubCounselor
 {
     [Key]
      public int Id { get; set; }
     //Foreign Key
     public int NewClubId { get; set; }
    [...]
     public NewClub NewClub { get; set; }
}

// Several more model classes like these ...

The solution

 public class MyContext : DbContext
    {
        public override int SaveChanges()
        {
            var entityInfoStr = String.Empty;
            var saveSuccess = false;
            var newClubPrimaryKeyId = 0;

            ObjectContext ctx = ((IObjectContextAdapter)this).ObjectContext;

            List<ObjectStateEntry> objectStateEntryList =
            ctx.ObjectStateManager.GetObjectStateEntries(EntityState.Added
                                                      | EntityState.Unchanged
                                                      | EntityState.Modified
                                                      | EntityState.Deleted).ToList();

            foreach (ObjectStateEntry entry in objectStateEntryList)
            {
                //Skip over relationships
                if (entry.IsRelationship) continue;

                //Make sure the entity is a member of the schema: NewClub[...]
                if (SecurityHelper.IsValidNewClubTableName(entry.EntitySet.Name))
                {

                    switch (entry.EntitySet.Name)
                    {
                        case "NewClubs":
                            var nc = entry.Entity as NewClub;
                            if (nc != null) { newClubPrimaryKeyId = nc.Id; }
                            break;

                        case "NewClubBuilders":
                            var ncb = entry.Entity as NewClubBuilder;
                            if (ncb != null) { newClubPrimaryKeyId = ncb.NewClubId; }
                            break;

                        case "NewClubCaseAnswers":
                            var ncca = entry.Entity as NewClubCaseAnswer;
                            if (ncca != null) { newClubPrimaryKeyId = ncca.NewClubId; }
                            break;

                        case "NewClubCommunityLeaders":
                            var nccl = entry.Entity as NewClubCommunityLeader;
                            if (nccl != null) { newClubPrimaryKeyId = nccl.NewClubId; }
                            break;

                        case "NewClubCounselors":
                            var ncc = entry.Entity as NewClubCounselor;
                            if (ncc != null) { newClubPrimaryKeyId = ncc.NewClubId; }
                            break;

                        case "NewClubEmails":
                            var nce = entry.Entity as NewClubEmail;
                            if (nce != null) { newClubPrimaryKeyId = nce.NewClubId; }
                            break;

                        case "NewClubKitOrders":
                            var ncko = entry.Entity as NewClubKitOrder;
                            if (ncko != null) { newClubPrimaryKeyId = ncko.NewClubId; }
                            break;

                        case "NewClubOrganizationChecklists":
                            var ncoc = entry.Entity as NewClubKitOrder;
                            if (ncoc != null) { newClubPrimaryKeyId = ncoc.NewClubId; }
                            break;                       

                        case "NewClubProspects":
                            var ncp = entry.Entity as NewClubProspect;
                            if (ncp != null) { newClubPrimaryKeyId = ncp.NewClubId; }
                            break;

                        case "NewClubRecruiterTrainingSchedules":
                            var ncrts = entry.Entity as NewClubRecruiterTrainingSchedule;
                            if (ncrts != null) { newClubPrimaryKeyId = ncrts.NewClubId; }
                            break;

                        case "NewClubRecruitingMember":
                            var ncrm = entry.Entity as NewClubRecruitingMember;
                            if (ncrm != null) { newClubPrimaryKeyId = ncrm.NewClubId; }
                            break;

                        case "NewClubRecruitingTeamEvent":
                            var ncrte = entry.Entity as NewClubRecruitingTeamEvent;
                            if (ncrte != null) { newClubPrimaryKeyId = ncrte.NewClubId; }
                            break;

                        case "NewClubSponsor":
                            var ncs = entry.Entity as NewClubSponsor;
                            if (ncs != null) { newClubPrimaryKeyId = ncs.NewClubId; }
                            break;
                    }

                    //Update the NewClub.LastActivityDate column
                    if (newClubPrimaryKeyId > 0)
                    {
                        string q = @"UPDATE NewClub SET LastActivityDate='" + DateTime.Now + "' WHERE Id="+newClubPrimaryKeyId;


                        using (var context = new MyContext())
                        {
                             var result = context.Database.ExecuteSqlCommand(q);
                        }


                    }


                }
            }

            try
            {

                 saveSuccess = base.SaveChanges() > 0;

            }
            catch (Exception e)
            {
                string ex = e.ToString();
                //Handle exception

            }

            return saveSuccess ? 1 : 0; 
        }
}
Slinky
  • 5,662
  • 14
  • 76
  • 130

1 Answers1

2

First, Handle the ObjectContext.SavingChanges event for this purpose. It is typically used to validate changed objects before new values are written to the database.

Secondly, define an interface, say IClub, with required set of operations, GetClubId() in your case. Implement the interface by each entity you need, in a way you need. This will let you check for interface implementation:

foreach (ObjectStateEntry entry in objectStateEntryList)
{
    IClub club = entry.Entity as IClub;
    if (!entry.IsRelationship && club!=null)
    {
          newClubPrimaryKeyId = club.GetClubId();
          ...
    }
}

PS. Interface implementation can be done in partial class to your entity, you can also adjust the t4 template if you use database first.


Also ObjectContext.Database.ExecuteSqlCommand is handy if you are updating multiple entities, in order not to query them all first. In your case you are updating a single item, so you can first query one

var club = context.NewClub.FirstOrDefault(c => c.Id == newClubPrimaryKeyId);

and next update it.

if (club!=null)
{
    club.LastActivityDate = DateTime.Now;
}
Andrew
  • 3,648
  • 1
  • 15
  • 29
  • First off, thanks for the quick and concise response. Never worked with these classes before so where do I implement ObjectContext.SavingChanges. Thanks – Slinky May 20 '14 at 13:07
  • 1
    it's an event. it is triggered when you call `SaveChanges`. Subscribe to it after you have your context created or within the context constructor: http://msdn.microsoft.com/en-us/library/system.data.objects.objectcontext.savingchanges%28v=vs.110%29.aspx – Andrew May 20 '14 at 13:11
  • btw, you are iterating through modified entities `foreach (ObjectStateEntry entry in objectStateEntryList)` and perform operation of updating the `LastActivityDate` each time, do you need that? I think getting first entity of `IClub` interface is what you need: `objectStateEntryList.FirstOrDefaut(entry=>entry is IClub)`, and get the club id from it. – Andrew May 20 '14 at 13:16