Community
Showing results for 
Search instead for 
Do you mean 
Reply

Retrieving History Item by History ID field.

Astute Commentator
Posts: 168
Country: United States

Retrieving History Item by History ID field.


 

Has anyone managed to retrieve a History Item from the database by ID using the ACT! Framework? On the beta there was a great call named GetHistoryByID which was succinctly removed on the final release.

 

I've tried all kinds of mechanisms with each one failing worse than the other. All the filtering seem to be directly related to filters re. the contacts and not history.

 

    I want to retrieve the history item by the history ID.

 

Does anyone have a working piece of code? I am using ACT! 16.

 

Thank you in advance.

 

T

Nickel Contributor
Posts: 175
Country: USA

Re: Retrieving History Item by History ID field.

If there is not a direct method to do this within the API (I don't have enough knowledge to say it is one way or the other), you could make your own method, within your application/plugin, that loops through the history items and returns the one that matches the ID that you pass in. While probably not the ideal way of doing it, I see no reason why it wouldn't work.
Astute Commentator
Posts: 168
Country: United States

Re: Retrieving History Item by History ID field.

First,

 

From what I see, you cannot retrieve all the history items. You can only retrieve contacts and then history items for those contacts. So to do what you state is really, really time consuming.

 

There has to be a way of getting a history item by ID. WHY did they take it away from the SDK?

 

Any better ideas?

 

T

Nickel Contributor
Posts: 175
Country: USA

Re: Retrieving History Item by History ID field.

I can't answer why that method was taken out, and I don't have v16 to reference, but in ACT 2013 there appears to be a method that would work. It is just HistoryManager.GetHistory(). It takes an "entityID" as System.GUID as a parameter. I see nothing that says what that "entityID" should be, but one could probably assume that it means history ID. Taking a quick look at the table structure for 2013, shows that HistoryID is a "uniqueIdentifier" in SQL Server, which equates to System.GUID in .NET.
Astute Commentator
Posts: 168
Country: United States

Re: Retrieving History Item by History ID field.

There is only one call that I see:

 

   ACTFM.Histories.GetHistory(guidContactID)

 

and that gets a list of history items for a contact. If you pass it the ACT! History ID, it fails (or just returns nothing).

 

All history calls are directly related to getting a history list from an ACT! Contact. As far as I can see, there is not a single call that retrieves an individual History by ID. I must be missing something. Any code out there that works?

 

T

Bronze Elite Contributor
Posts: 2,115
Country: United_Kingdom

Re: Retrieving History Item by History ID field.

The bad news is that it's not directly possible with the Act.Framework.Histories 

 

The only real way I can see using the supported API is by using the OLEDB provider. The benefit of this is that you can use direct SQL or linq to get the History obj you're after and it implements the Act! ACL so you don;t have to worry about authentication etc.

 

The down side is a biggy though, especially with secondary entities like Histories. THE OLEDB is painfully slow and at times can be unstable requiring rebuilding etc. If you have a very very large History datastore, it is completely feasible for the provider to timeout. Sadly it's not easily possible to override the default timeout settings without introducing further instability.

 

A third optyion could be to use the ActReader SQL access since you are only using it for reading and pulling out the Histories. You could using the tbl_contact_history table get the history and C|ontact IDs, that enable you to then use the Framework to find the Contact and then itterate through it's History collection, or better still convert it to a generic collection and then use a lambda expression to save yourself some fingerwork!

 

HTH

Vivek Gargav
Caldere Associates Ltd.
www.caldere.com
vgargav@caldere.com
My Blog
Nickel Contributor
Posts: 175
Country: USA

Re: Retrieving History Item by History ID field.

I was thinking about this, in that it was there in beta, but not in the final release. That got me thinking that maybe it is still there, just declared as "Private" in the VB world. I did some testing against 2013, and I was able to get to a method GetHistoryByID using reflection (a favorite namespace of mine). The following may be frowned upon by the ACT people, and it requires that you Import in the namespace "System.Reflection":

 Dim actf As New Act.Framework.ActFramework
            actf.LogOn(DBPath, UserName, Password)

            Dim returnHistory As Act.Framework.Histories.History
            Dim historyGUID As System.Guid
            System.Guid.TryParse("78AD5ABD-0D35-4AE1-AF96-004F0D03E157", historyGUID)   'Value is one grabbed from 2013 Demo Database
            Dim mi As MethodInfo = actf.Histories.GetType.GetMethod("GetHistoryByID", BindingFlags.NonPublic Or BindingFlags.Instance)

            returnHistory = CType(mi.Invoke(actf.Histories, New Object() {historyGUID}), Act.Framework.Histories.History)

  I have not actually tested the code to see if it would work and return the proper value, in this case, the proper History object. However, I have a good feeling that it will work, because when getting information about the parameter of the method, the parameter name was "historyID." The code is in VB, but if you need C#, running through a converter should work without any real issues.

Bronze Elite Contributor
Posts: 2,115
Country: United_Kingdom

Re: Retrieving History Item by History ID field.

knif,

 

yep right on the button. The GetHistoryByID is an internal method so the only way to call on it would be via reflection. Only problem is that you then wander into the realm of "un-supported" so be aware of this if you're developing a commercial product.

Vivek Gargav
Caldere Associates Ltd.
www.caldere.com
vgargav@caldere.com
My Blog
Nickel Contributor
Posts: 175
Country: USA

Re: Retrieving History Item by History ID field.

I agree with you on the commercial product, but depending on what is being done, it may be acceptable to Thatch.

It's very possible that it's been marked as private (at least since 2013) due to not being ready for primetime. It could've been set as a public method for the beta to put it through its paces, but then declared "not yet ready for final release."

I do have to agree with Thatch, that having a method like this would be nice. But I also have to wonder, knowing the basic structure of the ACT Framework, how does one just get a HistoryID, without any other entities (contact, group, company, etc.)
Bronze Super Contributor
Posts: 1,231
Country: USA

Re: Retrieving History Item by History ID field.

[ Edited ]

Yes, there is no way to get one history by GUID. It would be nice if SP added a GetHistoryByGuid() method to 16.1 but even if they do needed to support act! 2010 or better.

 

 

I wrote my own GetHistoryByGuid() function as seen below. EvenifSPaddsaget GetHistoryByGuid() methodinthe futureIwillcontinuetousethiscodeforbackwardcompatibility.

 

This code has a two-fold approach. 

  1. Use the OLEDB provider get the ParentEntityID from the contact, company, groups or opportunity table using the ENTITY_HISTORY bridge table. If the history is only attached to an last entity such as opportunity then there are three extra OLEDB calls. So be it.

  2. From the bridge table dataset I then use the ParentEntityID to get the top level entity using the SDK. Then loop thru all the histories attached to that entity. This way I reduce a loop to just the histories attached to one top level entity.

 

 

   Public Shared Function GetHistoryByGuid(ByVal HostFramework As Act.Framework.ActFramework, _
                                            ByVal HistoryGuid As System.Guid) As Act.Framework.Histories.History
        Try
            '------------------------------------
            ' Use the bridge table to find if this 
' history is attached to an Entity '------------------------------------ Dim dt As DataTable = New DataTable Dim selectCommand As String '----------------------------------- ' Attached to a CONTACT '----------------------------------- selectCommand = "SELECT CONTACT_HISTORY.CONTACTID " + _ "FROM CONTACT_HISTORY " + _ "WHERE (CONTACT_HISTORY.HISTORYID = '" + HistoryGuid.ToString() + "')" dt = Durkin.Common.Data.SQL.getSQLDataTable(HostFramework, _ Utilities.DurkinEnumorators.EntityDataMode.ACTOLEDB2, selectCommand, "History") If dt.Rows.Count > 0 Then Dim cContact As Act.Framework.Contacts.Contact = Nothing cContact = Durkin.Common.Classes.Contacts.GetContactByGuid(HostFramework, _ New Guid(dt.Rows(0).Item("CONTACTID").ToString())) If Not (cContact Is Nothing) Then For Each hist As Act.Framework.Histories.History In HostFramework.Histories.GetHistories(Nothing, cContact) If hist.ID = HistoryGuid Then Return hist End If Next End If End If '----------------------------------- ' Attached to a COMPANY '----------------------------------- selectCommand = "SELECT COMPANY_HISTORY.COMPANYID " + _ "FROM COMPANY_HISTORY " + _ "WHERE (COMPANY_HISTORY.HISTORYID = '" + HistoryGuid.ToString() + "')" dt = Durkin.Common.Data.SQL.getSQLDataTable(HostFramework, _ Utilities.DurkinEnumorators.EntityDataMode.ACTOLEDB2, selectCommand, "History") If dt.Rows.Count > 0 Then Dim cCompany As Act.Framework.Companies.Company = Nothing cCompany = Durkin.Common.Classes.Companies.GetCompanyByGuid(HostFramework, _ New Guid(dt.Rows(0).Item("COMPANYID").ToString())) If Not (cCompany Is Nothing) Then For Each hist As Act.Framework.Histories.History In HostFramework.Histories.GetHistories(Nothing, cCompany, Act.Framework.ComponentModel.AggregationType.All, Nothing, False) If hist.ID = HistoryGuid Then Return hist End If Next End If End If '----------------------------------- ' Attached to a GROUP '----------------------------------- selectCommand = "SELECT GROUP_HISTORY.GROUPID " + _ "FROM GROUP_HISTORY " + _ "WHERE (GROUP_HISTORY.HISTORYID = '" + HistoryGuid.ToString() + "')" dt = Durkin.Common.Data.SQL.getSQLDataTable(HostFramework, _ Utilities.DurkinEnumorators.EntityDataMode.ACTOLEDB2, selectCommand, "History") If dt.Rows.Count > 0 Then Dim cGroup As Act.Framework.Groups.Group = Nothing cGroup = Durkin.Common.Classes.Groups.GetGroupByGuid(HostFramework, _ New Guid(dt.Rows(0).Item("GROUPID").ToString())) If Not (cGroup Is Nothing) Then For Each hist As Act.Framework.Histories.History In HostFramework.Histories.GetHistories(Nothing, cGroup, Act.Framework.ComponentModel.AggregationType.All, Nothing, False) If hist.ID = HistoryGuid Then Return hist End If Next End If End If '----------------------------------- ' Attached to a OPPORTUNITY '----------------------------------- selectCommand = "SELECT OPPORTUNITY_HISTORY.OPPORTUNITYID " + _ "FROM OPPORTUNITY_HISTORY " + _ "WHERE (OPPORTUNITY_HISTORY.HISTORYID = '" + HistoryGuid.ToString() + "')" dt = Durkin.Common.Data.SQL.getSQLDataTable(HostFramework, _ Utilities.DurkinEnumorators.EntityDataMode.ACTOLEDB2, selectCommand, "History") If dt.Rows.Count > 0 Then Dim cOpportunity As Act.Framework.Opportunities.Opportunity = Nothing cOpportunity = Durkin.Common.Classes.Opportunities.GetOpportunityByGuid(HostFramework, _ New Guid(dt.Rows(0).Item("OPPORTUNITYID").ToString())) If Not (cOpportunity Is Nothing) Then For Each hist As Act.Framework.Histories.History In HostFramework.Histories.GetHistories(Nothing, cOpportunity) If hist.ID = HistoryGuid Then Return hist End If Next End If End If ' Could not find the history in any of the above entities Return Nothing Catch ex As Exception Throw ex End Try End Function

 

 

Hope this helps

-- Jim Durkin