2013-03-01 56 views
1

我已經研究瞭如何動態地改變這裏的數據源連接在計算器上許多不同的方式。我使用並驗證了幾乎所有可以找到的c#和vb.net示例,但不知怎的,事情不會按照他們的想法運行。動態更改數據庫類型,在Crystal Reports源等(爲Visual Studio 2012)

我們項目的想法是將舊報告(即使用xBase dll)的數據源連接更改爲crdb_ado.dll和VFPOLEDB提供程序以連接到Visual Foxpro DBF文件(每個文件代表一個表) 。

我已經下載了最新的水晶Developer版本的Visual Studio(2012年)在這裏:http://scn.sap.com/docs/DOC-35074 爲了能夠直接在VS使用這些組件,而引用的DLL在Program Files文件 - 業務對象目錄(如中所看到的其他例子)。

我試着通過VS調試器的舊版「更新」報告驗證內容(請參閱下面的代碼)以及Crystal Reports中新創建的報告(最新版本,它使用正確的路徑和設置連接到dbf )所以他們匹配。

不過,我遇到這些問題:

  1. 的代碼是能夠改變所有參數和屬性,但其保存放棄所有更改(文件不是隻讀)
  2. 更改table.location拋出一個COM異常(翻譯:無法加載數據庫中的數據,在錯誤報告)
  3. 當「附接」的報告的文檔對象到晶體報告觀看者發生同樣的情況。
  4. reportDocument.VerifyDatabase()顯然失敗
  5. 對於據我所看到的,所有的設置都在這兩個文件中

的開發環境似乎是windows 7/64/2012 VS臨。 Crystal Reports(XI或2011)安裝在本機上。我們所有的報告都是使用Crystal Reports的版本9和版本11創建的。

下面是確實更改了所有屬性或參數(表格位置除外)的一個修改代碼示例。我也使用過使用Propertybag對象的例子,但那些都不起作用。

reportDocument1.Load("path to document"); 

// also tried adding these two lines as a test 
reportDocument1.DataSourceConnections.Clear(); 
reportDocument1.DataSourceConnections[0].SetConnection(@"c:\testreports","",false); 

//changing of table data connections 
foreach (Table table in reportDocument1.Database.Tables) 
{ 
    ChangeTableLogonInfo(table); 
} 

// --- 
private void ChangeTableLogonInfo(Table table) 
{ 
    // server = place containing *.DBF files 
    table.LogOnInfo.ConnectionInfo.ServerName = @"c:\testreports\"; 
    // set to empty string (looking at generated report in CrRep) 
    table.LogOnInfo.ConnectionInfo.DatabaseName = ""; 
    table.LogOnInfo.ConnectionInfo.UserID = ""; 
    table.LogOnInfo.ConnectionInfo.Password = ""; 

    // create logon properties 
    var connectionAttributes = new DbConnectionAttributes(); 
    connectionAttributes.Collection.Set("Collating Sequence","Machine"); 
    connectionAttributes.Collection.Set("Data Source", @"c:\testreports"); 
    connectionAttributes.Collection.Set("Locale Identifier", 1033); 
    connectionAttributes.Collection.Set("OLE DB Services", -5); 
    connectionAttributes.Collection.Set("Provider", "VFPOLEDB"); //eg: SQLOLEDB 
    connectionAttributes.Collection.Set("Use DSN Default Properties",false); 

    // CLEAR and SET NEW attributes for the given table 
    table.LogOnInfo.ConnectionInfo.Attributes.Collection.Clear(); 
    table.LogOnInfo.ConnectionInfo.Attributes.Collection.Add(new NameValuePair2 { Name = "Database DLL", Value = "crdb_ado.dll" }); 
    table.LogOnInfo.ConnectionInfo.Attributes.Collection.Add(new NameValuePair2 { Name = "QE_DatabaseName", Value = "" }); 
    table.LogOnInfo.ConnectionInfo.Attributes.Collection.Add(new NameValuePair2 { Name = "QE_DatabaseType", Value = "OLE DB (ADO)" }); 
    table.LogOnInfo.ConnectionInfo.Attributes.Collection.Add(new NameValuePair2 { Name = "QE_LogonProperties", Value = connectionAttributes }); 
    table.LogOnInfo.ConnectionInfo.Attributes.Collection.Add(new NameValuePair2 { Name = "QE_ServerDescription", Value = @"c:\testreports" }); 
    table.LogOnInfo.ConnectionInfo.Attributes.Collection.Add(new NameValuePair2 { Name = "QE_SQLDB", Value = true }); 
    table.LogOnInfo.ConnectionInfo.Attributes.Collection.Add(new NameValuePair2 { Name = "SSO Enabled", Value = false }); 

    // gives a COM error 
    try 
    { 
     table.Location = "some-table-name";  
    } 
    catch (Exception e) 
    { 
     // handling 
    } 
} 

我們在Crystal Reports中注意到了一些令人討厭的東西。我想知道它是否與它有關:

當我們想通過CR本身來改變xbase連接時,我們不能從「xbase connection dbf」指向「vfpoledb connection dbf」(如果你理解我的點),而不會丟失報告中的所有字段。

我嘗試安裝了VS CR開發人員版本的32個和64位版本,但它似乎並沒有改變任何東西。

而且,接下來的一段代碼不工作在Visual FoxPro中(和我能夠在我的水晶閱讀這些轉換後的文件報告文檔查看器)。這只是討厭它不能輕易完成在C#(它似乎:))

lotest = CREATEOBJECT("crystalruntime.application.9") 
lorap = lotest.openreport("c:\factuur.rpt") 
loData = loRap.Database 
LOCAL lnI 
lnI = 1 
FOR EACH loTable IN lodata.tables 
     loconn = loTable.connectionproperties 
     loTable.dllname = "crdb_odbc.dll" 

     loConn.DeleteAll 
     IF lnI = 1 
      loCOnn.Add("Database", "Hoofding") 
     ELSE 
      loCOnn.Add("Database", "Detail") 
     ENDIF 
     loConn.Add("Database Type","ODBC") 
     loConn.Add("DSN","DBFACTw") 

     lnI = lnI + 1 
ENDFOR 

loRap.Saveas("c:\Factuur2.rpt",2048) 

任何想法或建議?謝謝

回答

2

我有同樣的問題,只有一個星期後,我設法解決它。

ApplyLogOnInfoCrystalDecisions.Shared.Table覆蓋ConnectionInfo屬性與報告文件中的原始屬性並僅更新用戶名和密碼。

您必須使用PropertyBag而不是DbConnectionAttributesCrystalDecisions.ReportAppServer.DataDefModel.Table而不是CrystalDecisions.Shared.Table

這是我工作的代碼:

PropertyBag connectionAttributes = new PropertyBag(); 
connectionAttributes.Add("Auto Translate", "-1"); 
connectionAttributes.Add("Connect Timeout", "15"); 
connectionAttributes.Add("Data Source", Server); 
connectionAttributes.Add("General Timeout", "0"); 
connectionAttributes.Add("Initial Catalog", Database); 
connectionAttributes.Add("Integrated Security", false); 
connectionAttributes.Add("Locale Identifier", "1040"); 
connectionAttributes.Add("OLE DB Services", "-5"); 
connectionAttributes.Add("Provider", "SQLOLEDB"); 
connectionAttributes.Add("Tag with column collation when possible", "0"); 
connectionAttributes.Add("Use DSN Default Properties", false); 
connectionAttributes.Add("Use Encryption for Data", "0"); 

PropertyBag attributes = new PropertyBag(); 
attributes.Add("Database DLL", "crdb_ado.dll"); 
attributes.Add("QE_DatabaseName", Database); 
attributes.Add("QE_DatabaseType", "OLE DB (ADO)"); 
attributes.Add("QE_LogonProperties", connectionAttributes); 
attributes.Add("QE_ServerDescription", Server); 
attributes.Add("QESQLDB", true); 
attributes.Add("SSO Enabled", false); 

CrystalDecisions.ReportAppServer.DataDefModel.ConnectionInfo ci = new CrystalDecisions.ReportAppServer.DataDefModel.ConnectionInfo(); 
ci.Attributes = attributes; 
ci.Kind = CrConnectionInfoKindEnum.crConnectionInfoKindCRQE; 
ci.UserName = Username; 
ci.Password = Password; 

foreach (CrystalDecisions.ReportAppServer.DataDefModel.Table table in Report.ReportClientDocument.DatabaseController.Database.Tables) 
{ 
    CrystalDecisions.ReportAppServer.DataDefModel.Procedure newTable = new CrystalDecisions.ReportAppServer.DataDefModel.Procedure(); 

    newTable.ConnectionInfo = ci; 
    newTable.Name = table.Name; 
    newTable.Alias = table.Alias; 
    newTable.QualifiedName = Database + ".dbo." + table.Name; 
    Report.ReportClientDocument.DatabaseController.SetTableLocation(table, newTable); 
} 

foreach (ReportDocument subreport in Report.Subreports) 
{ 
    foreach (CrystalDecisions.ReportAppServer.DataDefModel.Table table in Report.ReportClientDocument.SubreportController.GetSubreportDatabase(subreport.Name).Tables) 
    { 
     CrystalDecisions.ReportAppServer.DataDefModel.Procedure newTable = new CrystalDecisions.ReportAppServer.DataDefModel.Procedure(); 

     newTable.ConnectionInfo = ci; 
     newTable.Name = table.Name; 
     newTable.Alias = table.Alias; 
     newTable.QualifiedName = Database + ".dbo." + table.Name; 
     Report.ReportClientDocument.SubreportController.SetTableLocation(subreport.Name, table, newTable); 
    } 
} 

我希望這有助於還有其他開發者,因爲它是幾乎不可能找到SAP文檔或支持論壇在這個信息。

+0

我有一個類似的問題,但沒有使用ReportAppServer,因爲我只是在本地運行報告。我不能爲我的生活找出數據庫名稱的來源 - 它看起來並不像公開顯示的那樣。使用反射器進行檢查時,看起來好像在我的程序集(9.2.3333.0)中似乎將來自ConnectionInfo的信息傳遞給非託管代碼。 this._obfuscatedtablename_(connectionInfo.ServerName,connectionInfo.DatabaseName,connectionInfo.UserID,connectionInfo.Password,true); – agrath 2014-05-23 04:04:44

2

氖的答案對我來說是一個很大的幫助。除非服務器相同,否則我無法獲得大多數人談論的表循環ApplyLogOnInfo方法。他會用報告文件中的原始值替換所有內容,就像他觀察到的那樣。

在我的情況下,我只是試圖在web.config中使用連接字符串在dev/test/prod數據庫之間進行切換。使用DatabaseController.ReplaceConnection是最終爲我工作的。我必須克隆(深層複製)現有的ConnectionInfo並對少數相關屬性進行更改,而不是嘗試從頭建立一個或直接修改現有的屬性。

public static void SetReportLogOnInfo(ReportDocument report) 
    { 
     if (!report.IsLoaded) 
      report.Refresh(); //workaround for report.FileName empty error 

     foreach (CrystalDecisions.ReportAppServer.DataDefModel.ConnectionInfo oldInfo in report.ReportClientDocument.DatabaseController.GetConnectionInfos()) 
     { 
      var newInfo = oldInfo.Clone(true); 
      newInfo.UserName = [ConnectionString.UserID]; 
      newInfo.Password = [ConnectionString.Password]; 
      newInfo.Attributes["QE_LogonProperties"]["Server"] = [ConnectionString.DataSource]; 
      report.ReportClientDocument.DatabaseController.ReplaceConnection(oldInfo, newInfo, null, CrDBOptionsEnum.crDBOptionDoNotVerifyDB); 
     } 
    } 
相關問題