32k limit when adding small contact items using RDOFolder.Items.Add

  • Thread starter Thread starter Chris
  • Start date Start date
C

Chris

Hi,

I'm using Redemption's new RDO objects (4.0, very nice) and am having a
problem iterating through an sql table of contacts and converting them
into Exchange contacts. I am using RDOFolder.Items.Add and after
calling this about 260 times RDOFolder.Items.Add returns nothing. If I
keep a running total of the size of the contact items added the problem
occurs exactly when 32k of of total contacts have been added. I
imagine that a MAPITable is being used underneath but I don't know how
to reset or flush it in order to process more contacts. I've tried a
few things which you can see in the code below.

Cheers,
Chris

Here is the code snippet (vb.net):


For Each dr As DataRow In dt.Rows
With New MapiCodes
c = contactsFolder.Items.Add("IPM.Contact")
If c Is Nothing Then
MsgBox("c is nothing") ' This happens when
bufferSize reached 32000
End If

c.Fields(.CdoPR_TITLE) = dr("Title").ToString
c.Fields(.CdoPR_GIVEN_NAME) = dr("FirstName").ToString
c.Fields(.CdoPR_SURNAME) = dr("FamilyName").ToString
c.Fields(.CdoContact_EmailEmailAddress) =
dr("Email").ToString
c.Fields(.CdoPR_DISPLAY_NAME) =
dr("CalcFullNameInv").ToString
c.Fields(.CdoContact_FileUnder) = .CdoPR_DISPLAY_NAME
c.Fields(.CdoPR_COMPANY_NAME) =
dr("Institution").ToString
c.Fields(.CdoPR_BUSINESS_TELEPHONE_NUMBER) =
dr("Tel1").ToString
' c.Fields("urn:schemas:contacts:fileasid") = 32791
' c.Fields(.cdocontact
' .Add(CdoContact_FileUnderID, &HFFFFFFFF,
CdoPropSetID3)
c.Save()

bufferSize += c.Size
totalSize += c.Size
Debug.WriteLine(c.Size & "/" & bufferSize & "/" &
totalSize)
If bufferSize > 31000 Then
Debug.WriteLine("Now trying to reset")
' mapiUtils.Cleanup() ' Doesn't reset
contactsFolder = Nothing ' Doesn't reset
contactsFolder = GetFolderMapi(path,
publicRootFolder) ' Doesn't reset
bufferSize = 0
End If
End With
Next
mapiUtils.Cleanup()
 
Most likely you are running into the 255 RPC channels/process limit - each
Exchange object has an open RPC channel. Try to set each object to Nothing
as soon as you are done with it. Are you using VB 6 or VB.Net?

Dmitry Streblechenko (MVP)
http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool
 
Hi Dmitry. I'm using vb.net in this case. I counted the number of
objects created before failing and it does correspond to 255. Here is
my new code where I try to set the newly created contact object c to
nothing and then output various statistics:

For Each dr As DataRow In dt.Rows
With New MapiCodes
c = contactsFolder.Items.Add("IPM.Contact")
If c Is Nothing Then
' MsgBox("c is nothing")
End If

c.Fields(.CdoPR_DISPLAY_NAME_PREFIX) =
dr("Title").ToString
c.Fields(.CdoPR_TITLE) = dr("Function").ToString
c.Fields(.CdoPR_GIVEN_NAME) = dr("FirstName").ToString
c.Fields(.CdoPR_SURNAME) = dr("FamilyName").ToString
c.Fields(.CdoContact_EmailEmailAddress) =
dr("Email").ToString
c.Fields(.CdoPR_DISPLAY_NAME) =
dr("CalcFullNameInv").ToString
c.Fields(.CdoPR_COMPANY_NAME) =
dr("Institution").ToString
c.Fields(.CdoPR_BUSINESS_TELEPHONE_NUMBER) =
dr("Tel1").ToString

c.Save()

bufferSize += c.Size
totalSize += c.Size
cObjects += 1
Debug.WriteLine(cObjects & " " & c.Size & "/" &
bufferSize & "/" & totalSize)

c = Nothing
End With
Next

Here is the output:

countOfObject size of contact/buffer size/total size.
..
..
..
245 134/32830/32830
246 134/32964/32964
247 134/33098/33098
248 134/33232/33232
249 134/33366/33366
250 134/33500/33500
An unhandled exception of type 'System.NullReferenceException' occurred
in redempTest.exe
Additional information: Object reference not set to an instance of an
object.
The program '[3388] redempTest.exe' has exited with code 0 (0x0).

So it's failing after 250 contact objects. Add in the session, store,
public folder and contacts folder objects I also created and that
brings us pretty close to 255 - so your suggestion seems right on the
money.

Question is then, how do I release this objects in vb 6.0 and vb.net?
Setting c to nothing doesn't seem to work here (maybe this works in vb
6.0 but not with dotnet garbage collection ....).

Cheers,
Chris
 
Answered my own question. In dotnet garbage collecting it does the
trick. In vb 6.0 I don't know .... Thanks Dmitry for solving this.
Here is the final working code:

' Each Exchange object creates an RPC channel and the Exchange
server
' limits the number of channels to 255. So when creating a
large number
' of mapi objects we need to force periodic garbage collection
so that this
' limit is not exceeded. If the limit is reached, new objects
can not
' be created.

Dim c As RDOMail
Dim cObjects As Integer
Const MaxObjects = 240 ' Allow for a few other objects.

GC.Collect() ' Start off clean
cObjects = 0
Try
For Each dr As DataRow In dt.Rows
With New MapiCodes
If cObjects > MaxObjects Then
Debug.WriteLine("Garbage collection")
GC.Collect() : cObjects = 0
End If

c = contactsFolder.Items.Add("IPM.Contact")
If c Is Nothing Then
' Try garbage collecting in case MaxObjects
underestimated
' the number of objects.
GC.Collect() : cObjects = 0
c = contactsFolder.Items.Add("IPM.Contact")
If c Is Nothing Then Throw New Exception("Error
creating RDOMail contact item.")
End If

c.Fields(.CdoPR_DISPLAY_NAME_PREFIX) =
dr("Title").ToString
c.Fields(.CdoPR_TITLE) = dr("Function").ToString
c.Fields(.CdoPR_GIVEN_NAME) =
dr("FirstName").ToString
c.Fields(.CdoPR_SURNAME) =
dr("FamilyName").ToString
c.Fields(.CdoContact_EmailEmailAddress) =
dr("Email").ToString
c.Fields(.CdoPR_DISPLAY_NAME) =
dr("CalcFullNameInv").ToString
c.Fields(.CdoPR_COMPANY_NAME) =
dr("Institution").ToString
c.Fields(.CdoPR_BUSINESS_TELEPHONE_NUMBER) =
dr("Tel1").ToString

c.Save()

cObjects += 1
Debug.WriteLine(cObjects)
End With
Next
Catch ex As Exception
MsgBox(ex.ToString) ' TODO log this
Finally
session.Logoff()
mapiUtils.Cleanup()
End Try
 
Back
Top