Solved

Dataset size for my Crystal Report is TOO BIG for RAM

Posted on 2009-04-06
9
862 Views
Last Modified: 2013-12-01
I am using VS2008, VB.NET.  Created a simple Windows application that finds a list of JPG files in a specified Folder, loads the names of the JPG files into an XML file.  I use that XML file to read the JPG file names and load the actual JPG into a Byte() array in my Dataset.  That Dataset is then the DataSource for my Crystal Report that simply has two JPGs on each page.

PROBLEM: THe list of JPGs may be as many as 200, which then makes the Byte() Array very large and too large to pull into the Dataset in RAM.

QUESTION: How can I get the Crystal Report to maybe load JPG photos direct from the file names or from another XML file whcih has the Byte() array of the JPG data?
0
Comment
Question by:tgr2000
  • 6
  • 2
9 Comments
 
LVL 15

Assisted Solution

by:oobayly
oobayly earned 200 total points
ID: 24081917
Instead of using a dataset, you could try using a BindingList<>.
You would have to create a property for each column that's contained in the report. This way you can create a readonly property that provides the Image data by reading the data from the filename only when it's needed. You may get this to work as garbage collection may clear up the byte arrays once they're no longer needed.

As you see, I've been able to bind a BindingList<Foo> to a DataGridView. To be quite honest, I'm not sure if this will even work with Crystal reports, but it's worth a try.

Of course, creating a class may be quite tedious if there are to be a lot of properties. I quite often use OpenOffice (saves the Excel license) to create the private fields & the respective public properties.
public void CreateData(){
      BindingList<Foo> foo = new BindingList<Foo>();
      foo.Add(new Foo() { ImagePath = @"D:\Image1.JPG" });
      foo.Add(new Foo() { ImagePath = @"D:\Image2.JPG" });
      foo.Add(new Foo() { ImagePath = @"D:\Image3.JPG" });
      dataGridView1.DataSource = foo;
}
 
  public class Foo{
    private string imagePath;
 
    public string ImagePath {
      get { return imagePath; }
      set { imagePath = value; }
    }
 
    public byte[] ImageData {
      get {
        // Read the Image data into a byte array
        System.IO.FileStream fs = new System.IO.FileStream(imagePath,
          System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read);
        byte[] data = new byte[fs.Length];
        fs.Read(data, 0, data.Length);
 
        fs.Close();
        return data;
      }
    }
  }

Open in new window

0
 

Author Comment

by:tgr2000
ID: 24081978
BindingList, that sounds like something to try.  Any idea where the "List" is mantained? I think it may be maintained in RAM just as the Dataset is but I am not sure.  I'll certainly look into it.
0
 

Author Comment

by:tgr2000
ID: 24082010
I would like to do soemthing like...
Dim xCrystal as New CrystalReport1
xCrystal.SetDataSource("c:\MyPhotos\Photos.xml")

Then open the report.
Photos.xml has 3 columns...
JPGFileName (eg Photo_001.jpg)
JPGDescription (some text)
JPGByte (Image Data)
0
Webinar: Aligning, Automating, Winning

Join Dan Russo, Senior Manager of Operations Intelligence, for an in-depth discussion on how Dealertrack, leading provider of integrated digital solutions for the automotive industry, transformed their DevOps processes to increase collaboration and move with greater velocity.

 
LVL 15

Expert Comment

by:oobayly
ID: 24082048
The list will definately be kept in RAM as a dataset would be, I'm also presuming the ImageData is the largest component in terms of size.
If Crystal Reports enumerates throught the list the way I'd hope, the ImageData property will only be requested when the item is being written to the report. Once it's been written, there should be no more references to it remaining and the byte array should be garbage collected.

The difference in doing it this way that total size of the List should never be that large as the ImageData should on be in memory when it's being used.
0
 

Author Comment

by:tgr2000
ID: 24082069
OK, I understand what you are saying and I can see how that would possibly work.  Let me try to figure out how to get the Crystal Report bound to the BindingList and I will get back to you on my results.  Thanks for the idea.
0
 
LVL 100

Accepted Solution

by:
mlmcc earned 300 total points
ID: 24083740
Can you put the images into a database and run the report against the database rather than an in memory dataset?

mlmcc
0
 

Author Comment

by:tgr2000
ID: 24087140
Yes, that is a good option and is exactly why I was trying to XML as the "database".  I need a file based database so chose XML.  I don't want to keep the Image Data in a centralized DB as this app needs to float around with the JPGs and be used on laptops and other areas.  The trick is the user will copy the FOLDER (JPGs and DB) to the repository once thye are done creating the report.  I am currently creating a TEM PXML file that includes the ImageData, trying to open a Crystal report against that XML file, print the report, delete the XML.
Do you have any other suggestions for what kind of local, file based, DB I could use?
0
 

Author Comment

by:tgr2000
ID: 24087659
OK, I have a possible solution using a little help from several posts and a little more research.  Need just a nit more help.
I link my Crystal Report to an XML file.   I get the data fro mthe XML to show on the report... GREAT! I just push a new XML file before opening the report and it works EXCEPT...
Ho do I place an identifier (not sure that is the correct word) in an XML file to identify the field as ByteArray or ImageData or what ever it is I need?
0
 

Author Comment

by:tgr2000
ID: 24089027
Great, I have a solution that works very well.  I keep all BUT the Image Data in XML and write the XML to local FOLDER with JPGs.  That gives me the description, JPG file name and few other TEXT fields that I need to KEEP with the JPGs.

Then, to open the report, I read the XML and add the ImageData via Stream into a LOCAL DB that I created via Visual Studio.  I empty the LOCAL DB before inserting the records each time prior to opening the Crystal Reports.  The Crystal Reports is connected to the LOCAL DB.

This Works perfect for my needs.

Thanks to both, I learned from you suggestions, combined a couple ideas, did a little more research and I now have a fully functional solution.

I would like to assign points to both parties? I'll see if that is possible.  Thanks again.
0

Featured Post

Master Your Team's Linux and Cloud Stack

Come see why top tech companies like Mailchimp and Media Temple use Linux Academy to build their employee training programs.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

It is a common problem that often server suffers from the lack of space on system volume. Old servers or new ones from vendors come with preformatted small volume - 5-6GB in total and after installing updates or applications the free space on system…
I previously wrote an article addressing the use of UBCD4WIN and SARDU. All are great, but I have always been an advocate of SARDU. Recently it was suggested that I go back and take a look at Easy2Boot in comparison.
Microsoft Active Directory, the widely used IT infrastructure, is known for its high risk of credential theft. The best way to test your Active Directory’s vulnerabilities to pass-the-ticket, pass-the-hash, privilege escalation, and malware attacks …
In an interesting question (https://www.experts-exchange.com/questions/29008360/) here at Experts Exchange, a member asked how to split a single image into multiple images. The primary usage for this is to place many photographs on a flatbed scanner…

808 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question