Crystal Report with Subreport failing on Windows 7 x64 - c#

I have a C# .NET WinForms application that uses Crystal Reports.
Crystal reports run fine on both x32 and x64 systems with the exception of reports containing subreports. Any report containing a subreport fails with the wonderful: "Log on failed" at ...VerifyDatabase() but only on x64 systems.
I have seen and fixed this problem in the past by unchecking Verify Database on every print, making sure the no data is being saved with the report and ensuring the correct driver and connection methods are being used in the designer. This problem is not going away and seems to only be affecting reports with subreports.
All projects in the solution are set to build to x32.
The x64 systems have the CR 32bit runtime installed.
The SQL Native Client is also installed.
I have tried many different combinations of report preparations steps like not verifying the database, not refreshing the report, verifying and not refreshing, refreshing and not verifying... it goes on and on.
Here is the current preparation method being used:
private T GetReport<T>() where T: ReportDocument, new()
{
var report = new T();
var connectionStringBuilder
= new SqlConnectionStringBuilder(this.ConnectionString);
var connectionInfo = new ConnectionInfo
{
DatabaseName = connectionStringBuilder.InitialCatalog,
UserID = connectionStringBuilder.UserID,
Password = connectionStringBuilder.Password,
ServerName = connectionStringBuilder.DataSource
};
Action<ReportDocument, bool, bool> setConnection = (document, verify, refresh) =>
{
document.DataSourceConnections.Clear();
document.DataSourceConnections[0].SetConnection(
connectionStringBuilder.DataSource,
connectionStringBuilder.InitialCatalog,
connectionStringBuilder.UserID,
connectionStringBuilder.Password
);
document.DataSourceConnections[0].IntegratedSecurity = false;
/*
foreach (Table table in document.Database.Tables)
{
var tableLogOnInfo = table.LogOnInfo;
tableLogOnInfo.ConnectionInfo = connectionInfo;
table.ApplyLogOnInfo(tableLogOnInfo);
}
* */
//document.SetDatabaseLogon(connectionInfo.UserID, connectionInfo.Password, connectionInfo.ServerName, connectionInfo.DatabaseName);
if (verify)
document.VerifyDatabase();
if (refresh)
document.Refresh();
};
for (var index = 0; index < report.Subreports.Count; index++)
{
var subreportName = report.Subreports[index].Name;
var subreport = report.OpenSubreport(subreportName);
setConnection(subreport, false, false);
}
setConnection(report, true, true);
return report;
}
SOLVED: I have gotten the report to work. I am not sure what part of this solution actually solved the problem but these are the steps I took.
I checked the data source per aMazing's suggestion below. (It was already OLE DB)
I removed all referenced to Crystal Reports in all projects in the solution.
I re-added the Crystal Reports references and made sure all the references were the same version and made sure all references were set to 'Specific Version' = True.
I set 'Copy Local' to True on the CR references on one project in the solution.
I changed the call to the **setConnection** to not verify.
I un-commented foreach table.ApplyLogOnInfo(tableLogOnInfo) section.
I'm not sure why it works now but it does. The table.ApplyLogOnInfo was un-commented in many of the permutations I tried earlier. Maybe I never hit this specific combination... but I don't care at this point.

SOLVED: I have gotten the report to work. I am not sure what part of this solution actually solved the problem but these are the steps I took.
I checked the data source per aMazing's suggestion below. (It was already OLE DB)
I removed all referenced to Crystal Reports in all projects in the solution.
I re-added the Crystal Reports references and made sure all the references were the same version and made sure all references were set to 'Specific Version' = True.
I set 'Copy Local' to True on the CR references on one project in the solution.
I changed the call to the **setConnection** to not verify.
I un-commented foreach table.ApplyLogOnInfo(tableLogOnInfo) section.
I'm not sure why it works now but it does. The table.ApplyLogOnInfo was un-commented in many of the permutations I tried earlier. Maybe I never hit this specific combination... but I don't care at this point.

Because I couldnt add a comment, this was the only way I could reply.
What SQL server are you using? I had something similar before.
Check the following on both report and sub report:
1) Right Click Datasource Properties
2) Select Set Datasource Location
3) On the connetion that the report is using, click expand Properties
4) Confirm that the Database Type = OLE DB (ADO) and Provider is SQLOLEDB.
That fixed my problem. I had set it to SQLNative Client before which was failing.
Hope it helps.
Thanks

Check if you have an Access database or any other 32 bit datasource in any of the subreports.

I had this same problem recently. I found the cause to be not setting the datasource, which in my case was due to an incorrect if statement, meaning the following line was not running:
repdoc.Subreports["SubReportName.rpt"].SetDataSource((DataTable)MyDataTable);
Hope this is of use.

Related

Attempting to run Update Query doesn't update dataset

So I have a Database that I created a Dataset from, I'm attempting to run an Update on it and I cannot get it to update the Dataset (and subsequently the Database) with the result. I built the Query using Visual Studio's query builder and when I run it through there it changes the data in the way that it should. When I run the code I put in a MessageBox to show the number of rows the query changed and it is returning 1 as it should. I'm at a loss as to why it won't 'commit' the update and I'm sure I'm missing something very simple.
Here is the Query I setup (named "UpdateQuery")
UPDATE Bug_Master
SET Name = #Name, Test_App = #Test_App, Bug_Type = #Bug_Type, Bug_Active = #Bug_Active, Bug_Description = #Bug_Description, Bug_Keywords = #Bug_Keywords
WHERE (Id = #Original_Id);
In the Load event for the form I have
this.bug_MasterTableAdapter.Fill(this.bugManagerDataSet.Bug_Master);
And here is where I am calling the Query and trying to update (I know I should use 'using' but I'll pretty up the code after I get this to work so forgive the inelegance)
SqlConnection connection = new SqlConnection(strSQLConnectionString);
connection.Open();
int iResult = bug_MasterTableAdapter.UpdateQuery("Error One 1", "PassVault", "Runtime", "True", "Description Test", "Keywords Test", 1);
MessageBox.Show(iResult.ToString());
bug_MasterTableAdapter.Update(bugManagerDataSet.Bug_Master);
connection.Close();
As I mentioned above the MessageBox shows '1'. Is there a critical step I'm missing on how to do this? It has been a long time since I messed with SQL so I've had to bumble my way back to it and have no doubt I've missed/messed up some things.
Thanks in advance.
erik
Found the solution. Turns out the 'copy to output directory' property on the database file was set to 'always copy'. So when I ran the program it would make changes to the database in the \bin\debug folder while I was looking at the one in the app folder. Then when I would restart the program to check the values in there it would overwrite the changed version of the database in \bin\debug with the unchanged version from the project.
So, the upshot is for anyone else that runs into something similar is set the 'Copy to Output Directory' option on the database to 'Copy if Newer'.
Thanks to all who took a look.
erik

Local ReportViewer Fails at Unnecessary Login to Database

I have inherited an application that runs small reports locally using Microsoft Web ReportViewer. Our application allows you to "Preview/Print" a report by clicking on a specific button that routes the user to a URL that allows them to download the report as a PDF. We have recently received the requirement to save these PDFs to the document table in our database. I have been able to get this to work successfully on localhost; however, when I publish the application to our IIS server, I get the following error:
System.Data.SqlClient.SqlException: Login failed for user 'Domain\Servername$'.
I've reviewed all of the sites that I could find involving this error (including this one) - most point to adding the server account to the SQL database; however, this shouldn't be an issue, since the button to preview/print the document is still functional and works as expected when the application is published and all of the data is held in a local object, which was previously pulled from the database (the model parameter below). The button and the auto-generation feature use the same two methods to create the PDF document(see below).
Here's some code:
public static byte[] CreatePDFDocument(DocumentTemplateType template, Request model)
{
Warning[] warnings;
string[] streamIds;
string mimeType = string.Empty;
string encoding = string.Empty;
string extension = string.Empty;
ReportViewer viewer = new ReportViewer();
viewer.ProcessingMode = ProcessingMode.Local;
viewer.LocalReport.ReportEmbeddedResource = "Xxx.Xxx.Bll.ReportViewerRDLCs." + template.RdlcFilename;
switch ((DocumentType)template.DocumentTypeId)
{
case eDocumentType.Report1:
viewer.LocalReport.SetParameters(GetForm1Parameters(model));
break;
/**
* Several other reports are in this switch. All reports have the
* same issue - all but one are removed for brevity.
*/
}
byte[] bytes = viewer.LocalReport.Render("PDF", null, out mimeType, out encoding, out extension, out streamIds, out warnings);
return bytes;
//return new byte[5] {5,6,7,8,9}; - used for troubleshooting.
}
public static List<ReportParameter> GetReport1Parameters(Request model)
{
List<ReportParameter> rptParams = new List<ReportParameter>();
//Start comment
rptParams.Add(new ReportParameter("EmployeeFullName", string.Format("{0:NN}", model.Employee)));
rptParams.Add(new ReportParameter("EmployeePhoneNumber", string.Format("{0:(###) ###-####}", Convert.ToInt64(model.Employee.PhoneNumber))));
rptParams.Add(new ReportParameter("HrchyShortDesc", model.Employee.HrchyShortDesc));
rptParams.Add(new ReportParameter("RequestDate", model.RequestDate.ToShortDateString()));
rptParams.Add(new ReportParameter("RequestRequested", model.RequestRequestType));
rptParams.Add(new ReportParameter("ReasonForRequest", model.RequestRequestReason));
rptParams.Add(new ReportParameter("LogNumber", model.CaseId));
if (!string.IsNullOrWhiteSpace(model.TimeSensitiveReason)) rptParams.Add(new ReportParameter("TimeSensitiveReason", model.TimeSensitiveReason));
var lastAction = model.LastActionOfType(WorkflowStateActionType.EmployeeConfirmation);
if (lastAction != null)
{
rptParams.Add(new ReportParameter("TodaysDate", lastAction.ActionDate.ToShortDateString()));
rptParams.Add(new ReportParameter("EmpConfirmed", "true"));
}
else rptParams.Add(new ReportParameter("TodaysDate", DateTime.Now.ToShortDateString()));
//end comment
return rptParams;
}
Through a lot of commenting in and out and pushes to our server, I've deduced the following:
From what I can tell, the error occurs on calling GetReport1Parameters. In the code above, I included a start and end comment - I've commented out everything in between, leaving only the list initialization and return statement (of an empty list) and still received the error.
I've commented out the call to GetReport1Parameters and returned a nonsensical byte array and didn't receive an Exception.
All functionality works fine on localhost and when I step through the functions, all of the variables seem to appear normal.
Things I've tried to do to remedy the situation:
1. Removed connection strings from the app.config, so that the application has to go to the web.config to get the correct strings (even though they were the same).
2. Commented in and out different sections of code to determine the problem area.
3. Tried calling the GetReport1Parameters method and returning null, leading to a null reference exception.
4. Tried calling the GetReport1Parameters with an empty parameter list, leading to the error mentioned above.
5. Tried running the report with no parameters (not even a blank list), got a ReportProcessingException for missing params.
Some additional information:
We use a service account for the application using impersonate identity in the web.config. That line is commented out on localhost, but is running on IIS.
All of other database interaction works correctly.
All of our database interaction is done using LINQ to SQL - model is an object based off of a database table, with some additional information that is calculated dynamically.
My desired outcome is that both the autogenerated documents and the preview/print documents both work. I have a feeling that this may be something simple that I'm overlooking, but I've already spent several hours today trying to fix this.
I can't think of any other pertinent information, but if you have questions I'll be more than happy to answer them.
Edit: Additional attempts to find solution:
Tried setting LINQ Deferred Loading equal to false. This caused more problems than it solved.
Implemented IReportServerCredentials and assigned the ReportViewer's ServerReport.ReportServerCredentials with the correct database credentials.
Assigned all pertinent report parameters to a Dictionary, and then called .ToString() on every object to ensure that it is pulled from the database. Then assigned those strings from the dictionary to the report parameters, so that ReportViewer should be receiving the data from the string pool, as opposed to pulling it from the database.
Even though you are using an ObjectDataSource to pass data to your report, Report Viewer will still invoke the Select method, which in turn could cause database access to occur. So even though it may seem that the login is unnecessary, you would need to dig into the data access methods you supplied with your ObjectDataSource to know for sure.
The error you are getting is being caused by a bug in Report Viewer 2010 that is describe in the following Microsoft Connect article:
ReportViewer.LocalReport.Render and ReportViewer.LocalReport.SetParameters changes ImpersonationLevel to None
Although the article mentions this problem should be fixed in Service Pack 1, it does not appear to be the case. I have not verified if this problem is fixed in Report Viewer 2012.
I worked around the problem by changing my data access layer to compare the current identity against the one in my HttpContext and restore it if necessary using the following code snippet:
System.Security.Principal.IIdentity id = System.Web.HttpContext.Current.User.Identity
if (id.Name != System.Security.Principal.WindowsIdentity.GetCurrent().Name)
{
context = (id as System.Security.Principal.WindowsIdentity).Impersonate()
}
I do this right before I connect to the database and undo it as soon as the connection is open.
I am not exactly thrilled with this workaround, mainly because now my data access layer is referencing the UI layer (System.Web).

Crystal Reports keeps prompting for Parameter

I am having a terrible problem with crystal report 2010 for .net 4.0 (I am using the fixed 13.0.1 version but 13.0.4 is released). No matter which way I try, I am always getting a prompting dialogue box to input my one parameter value the first time.
CrystalReportViewer1.ReportSource = CustomerReport1;
CustomerReport1.Database.Tables[0].SetDatasource ( this.dataset);
CustomerReport1.SetParameterValue("PathLocation", Location.Text);
CustomerReport1.Parameter_PathLocation.CurrentValues.Add(Location.Text) // to be safe using CS 2010 for .net 4
CrystalReportViewer1.ReuseReportParametersOnRefresh = true; // to prevent from showing again and again.
I also tried this:
CustomerReport1.Database.Tables[0].SetDatasource ( this.dataset);
CustomerReport1.SetParameterValue("PathLocation", Location.Text);
CrystalReportViewer1.ReportSource = CustomerReport1;
And this:
CustomerReport1.Database.Tables[0].SetDatasource ( this.dataset);
CustomerReport1.Parameter_PathLocation.CurrentValues.Add(Location.Text)
CrystalReportViewer1.ReportSource = CustomerReport1; // the parameter in the report has Optional Parameter = false, Static , Multiple Value = false .
Can anyone please help? I am getting frustrated with this. It worked in previous versions, but now I am getting this prompt box.
Thank you.
Finally found the solution. It doesn't prompt if we set the DataSource after the ParameterValue.
So anyone of those will work if we put them in this order:
// First, call SetParameterValue. Then, call SetDatasource.
CustomerReport1.SetParameterValue("PathLocation", Location.Text);
CustomerReport1.Database.Tables[0].SetDatasource(this.dataset);
CrystalReportViewer1.ReportSource = CustomerReport1;
Thank you all.
create the parameter but do not assign it a formula using selection formula -> record. Apply this parameter from vb or c#.net IDE by creating a text box,a label and a button. Put the selection formula on click button procedure.

Crystal Reports and Login issue

I need some help.
Actually, I've read about this problem, and I thought that I've resolved it, but it keeps bothering me.
It's about different logins at developing and production enviroment.
This was supposed to be solution (EF and SQL Server):
SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder((model.Connection as EntityConnection).StoreConnection.ConnectionString);
ConnectionInfo ci = new ConnectionInfo();
ci.ServerName = builder.DataSource;
ci.DatabaseName = builder.InitialCatalog;
ci.UserID = builder.UserID;
ci.Password = builder.Password;
report.SetDatabaseLogon(ci.UserID, ci.Password, builder.DataSource, ci.DatabaseName);
foreach (CrystalDecisions.CrystalReports.Engine.Table tbl in report.Database.Tables)
{
TableLogOnInfo logon = tbl.LogOnInfo;
logon.ConnectionInfo = ci;
tbl.ApplyLogOnInfo(logon);
}
I extract login information from Entity Connection and apply it to all the tables in report. That should do the trick. I added SetDatabaseLogon() only to be sure, but that's not required.
Now, when I run report in production enviroment, report pops up a Database login screen showing CORRECT server name (production server), NOTHING next to database (that is my concern), proper username, and no password, asking to type in login information.
I type it in, but CR says "Login failed. Please try again". I mean WTF. I use the very same credential to connect to database with Management Studio.
I am using WPF viewer, BTW.
I am really stuck here, I've done some debugging, and connection info gets all the right data, so it must be report who is the culprit, but what should I do?
Any help would be appreciated. I hope somebody has stumbled to a same problem before me.
Regards
I had a problem with using "SetDatabaseLogon"
I changed by
report.DataSourceConnections[0].SetConnection("Servername","InitialCatalog", "UserID", "Password");
I hope this will helpful to someone.
Looking at the code on my Blog Post that does the same jobs, I can see a few differences:
Set tbl.Location to itself (this might be re initializing something internally - it didn't work without it).
Put your code in a method that you can re-call to handle sub reports:
My version never needs to call report.SetDatabaseLogon
Other than that they're basically identical.
Code:
void SetConnection(ReportDocument rd, crConnectionInfo ci)
{
foreach (CrystalDecisions.CrystalReports.Engine.Table tbl in rd.Database.Tables)
{
TableLogOnInfo logon = tbl.LogOnInfo;
logon.ConnectionInfo = ci;
tbl.ApplyLogOnInfo(logon);
tbl.Location = tbl.Location;
}
if (!rd.IsSubReport) {
foreach {ReportDocument sd in rd.SubReports) {
SetConnection(sd,ci)
}
}
}
(Note: Just hand coded this, so check it before you use it).
This works on the VS2008 version of crystal reports (forget what it was called).
EDIT: One other thing, in my connection initialization, there are a couple of extra properties set:
ci.Type = ConnectionInfoType.SQL;
ci.IntegratedSecurity = false;
It was totally stupid problem, and i solved it by chance. Installation of Crystal Reports on my desktop computer was crooked or something, so whenever I edited something with database expert (add some tables, for example), it spoiled my report. All I did is use "set database location" option on my laptop, and now my reports run flawlessly.

Can't open Sqlite database in read-only mode

I have a Sqlite database that I include with my MonoTouch app. It has worked fine for me so far, but now I want to open it in read-only mode rather than read-write.
So I have changed the connection string to include 'Read Only=True', but when I call Open(), I get the following error:
Library used incorrectly (at Mono.Data.Sqlite3.Open)
If I dig into the exception it shows
_errorCode = Misuse
and that's about all the info it gives.
Here's the code:
var _conn = new SqliteConnection("Data Source=db/sampleDb;Read Only=True");
_conn.Open ();
You found a bug in Mono.Data.Sqlite.dll.
The Create flag is appended (by default) before the ReadOnly flag is parsed and set. The resulting flag is invalid and sqlite reports an error.
I will fix this for future releases (of Mono and MonoTouch...). If this blocks you then please open a bug report on http://bugzilla.xamarin.com and I'll attach a fixed assembly (with instructions to replace the existing one) to the bug report.
This worked for me (aspnet core):
var _conn = new SqliteConnection("Data Source=db/sampleDb;mode=ReadOnly");
Have you tried?:
var _conn = new SqliteConnection("Data Source=db/sampleDb;mode=ro");
Your code is correct, I just tried it (not using MonoTouch) and it worked for me.
Do you have the latest version of System.Data.SQLite.dll?
If yes, then maybe it's a problem related to MonoTouch.

Categories