In one of our Dynamics CRM app we make heavy use of facility/equipment calendars. Ordinarily this would not be even worthy of mention, never mind a post, but Microsoft decided that it would be a bad idea to delete those calendars. Nominally deletion of calendars is supported in the SDK documentation, but in practice, things are a little bit different.
Anyway, the fact of the matter is that we have built up a rather large collection of calendars and calendar rules (90K & 550K last time I checked) and this is slowing our users down. Some operations are slightly slower, to the point that they have not noticed, whereas others are simply painstakingly slow (A custom screen can take up to 1 minute to load), so I (re)used a very simple method to delete a calendar:
1 [WebMethod]
2 public bool Delete(string strEntityName, string strEntityGuid)
3 {
4 try
5 {
6 CreateLog("Trace", "Delete:: Delete( string strEntityName, string strEntityGuid)",
7 "1. IN. strEntityName: " + strEntityName +
8 " - strEntityGuid: " + strEntityGuid + " .");
9
10
11
12
13
14
15 Guid objEntityId = new Guid(strEntityGuid);
16
17 CreateLog("Trace", "Delete:: Delete( string strEntityName, string strEntityGuid)", "2. About to Call Delete.");
18
19 lCrmService.Delete(strEntityName, objEntityId);
20
21 CreateLog("Trace", "Delete :: Delete( string strEntityName, string strEntityGuid)", "3. Delete Complete. Returning True");
22 CreateLog("Audit", "Delete :: Delete( string strEntityName, string strEntityGuid)", "Deleted Call with ID: " + strEntityGuid + " .");
23
24 return true;
25 }
26 catch (Exception ex)
27 {
28 CreateLog("Error", "Delete :: Delete( string strEntityName, string strEntityGuid)", "Error: " + ex.ToString() + " .");
29 return false;
30 }
31 }
but alas I got the following error message, when I passed in a calendar:
Crm Exception: Message: The object you tried to delete is associated with another object and cannot be deleted., ErrorCode: -2147220953
Fair enough, I thought, I need to delete the calendarrules first, unfortunately I got this error message:
Crm Exception: Message: The 'Delete' method does not support entities of type 'calendarrule'., ErrorCode: -2147219456
No dice. The irritating part is that we can delete the calendars directly with a sql statement, a rather convoluted sql statement actually, but this is:
- unsupported
- would require a lot of testing
probably definitely a bad idea
After a bit of digging around and a somewhat inspired guess, I have managed to delete calendars, the code, see below, needs to be tested and it's not production ready, you don't say, but it does delete calendars, at least the calendars linked to facilities/equipment, which is the ones
we are interested about.
Source Code:
1 <summary>
2
3 </summary>
4 <param name="strEntityGuid"></param>
5 <returns></returns>
6 [WebMethod]
7 public bool TDelete(string strEntityGuid)
8 {
9 try
10 {
11 CreateLog("Trace", "DeleteEntity :: TDelete( string strEntityName, string strEntityGuid)",
12 "1. IN. strEntityGuid: " + strEntityGuid + " .");
13
14
15 calendar acal = DeleteCalendarRules(strEntityGuid);
16
17 if (acal != null)
18 {
19
20
21
22
23
24 string equipmentid = System.Text.RegularExpressions.Regex.Match(acal.name.ToUpper(), @"[A-F0-9]{8}-[A-F0-9]{4}-[A-F0-9]{4}-[A-F0-9]{4}-[A-F0-9]{12}").Value;
25
26
27 equipment myequip = (equipment)lCrmService.Retrieve(EntityName.equipment.ToString(), new Guid(equipmentid), new AllColumns());
28
29
30 calendar equipmentcal = (calendar)lCrmService.Retrieve(EntityName.calendar.ToString(), myequip.calendarid.Value, new AllColumns());
31
32
33 string fetch = "<fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='false'><entity name='calendarrule'><attribute name='calendarruleid'/><filter type='and'><condition attribute='calendarid' operator='eq' value='" +
34 myequip.calendarid.Value.ToString() + "'/><condition attribute='innercalendarid' operator='eq' value='" + strEntityGuid + "'/></filter></entity></fetch>";
35
36 string result = lCrmService.Fetch(fetch);
37
38 XmlDocument doc = new XmlDocument();
39 doc.LoadXml(result);
40 string guid = doc.SelectSingleNode("//result").FirstChild.InnerText;
41
42
43
44
45 for (int i = 0; i < equipmentcal.calendarrules.Length; i++)
46 {
47 calendarrule mycalrul = equipmentcal.calendarrules[i];
48
49 if (mycalrul.calendarruleid.Value == new Guid(guid))
50 {
51 equipmentcal.calendarrules[i] = null;
52 lCrmService.Update(equipmentcal);
53 }
54 }
55
56
57 TargetDeleteCalendar target = new TargetDeleteCalendar();
58 target.EntityId = new Guid(strEntityGuid);
59
60
61 DeleteRequest delete = new DeleteRequest();
62 delete.Target = target;
63
64 CreateLog("Trace", "DeleteEntity :: TDelete( string strEntityName, string strEntityGuid)", "2. About to Call Delete.");
65
66
67 DeleteResponse deleted = (DeleteResponse)lCrmService.Execute(delete);
68
69 CreateLog("Trace", "DeleteEntity :: TDelete( string strEntityName, string strEntityGuid)", "3. Delete Complete. Returning True");
70 CreateLog("Audit", "DeleteEntity :: TDelete( string strEntityName, string strEntityGuid)", "Deleted Callaback with ID: " + strEntityGuid + " .");
71
72 return true;
73 }
74 else
75 {
76 return false;
77 }
78 }
79 catch (Exception e)
80 {
81 CreateLog("Error", "DeleteEntity :: TDelete( string strEntityName, string strEntityGuid)", "Error: " + e.ToString() + " - source: " + e.Source + " .");
82 return false;
83 }
84 }
85
86 <summary>
87
88
89 </summary>
90 <param name="strEntityGuid"></param>
91 <returns></returns>
92 private calendar DeleteCalendarRules(string strEntityGuid)
93 {
94 try
95 {
96 calendar calTBDeleted = (calendar)lCrmService.Retrieve(EntityName.calendar.ToString(), new Guid(strEntityGuid), new AllColumns());
97
98
99 calTBDeleted.calendarrules = null;
100
101 lCrmService.Update(calTBDeleted);
102
103 return calTBDeleted;
104 }
105 catch (Exception e)
106 {
107
108 return null;
109
110 }
111 }