Discussion:
ODBC+Crystal+dotnetвопрос
(слишком старое сообщение для ответа)
Mike
2005-04-25 17:21:44 UTC
Permalink
Есть проект ASP.net, в котором нужно считать инфу с некой БД
(находящейся на линуксовом сервере - T-Bred, если кто в курсе) и выдать
ее в виде красивого Crystal отчета.

В стандартном виндусовом списке ODBC-драйверов нужного нету, ставим его
с сидюка фирмы. Далее создаем ODBC-соединение, прописываем в нем IP,
login и password, cоздаем прямо в .NET-овском проекте файл CrystRep.rpt,
открываем в Add/Remove Database нужное ODBC-соединение, выбираем таблицу
и несколько полей, далее в другом файле проекта пишем:
CrystalReportViewer1.ReportSource="CrystRep.rpt";
Запускаем - все работает, все красивенько выдается.

Скажем, по какому-то конкретному Vendor-у. Добавляем строчку:
CrystalReportViewer1.SelectionFormula=
"{table1.VENDOR_NUMBER} = '77'";
Все по-прежнему работает.

Hо нужно нечто большее. Hапример, в одной таблице - инфа про Purchase
Orders и номера Vendors, в другой - инфа про самих Vendors: номер, имя,
адрес, телефон и т.д. Hужно выдать отчет, сгруппированный по Vendors,
чтобы в заголовке каждой группы было имя, адрес, телефон и т.д., а в
Details уже шел список Purchase Orders этого конкретного Vendor-а.
Присоединяем еще одну таблицу, в закладке Links отмечаем VENDOR_NUMBER,
запускаем - ошибка:

Description: An unhandled exception occurred during the execution of the
current web request. Please review the stack trace for more information
about the error and where it originated in the code.

Exception Details: CrystalDecisions.CrystalReports.Engine.
InternalException: Failed to open a rowset.

Source Error: An unhandled exception was generated during the execution
of the current web request. Information regarding the origin and
location of the exception can be identified using the exception stack
trace below.

Ладно, убираем Links (может, ODBC не поддерживает всякие Inner Join?),
вместо этого ставим:
CrystalReportViewer1.SelectionFormula=
"{table1.VENDOR_NUMBER} = {table2.VENDOR_NUMBER}";

Все равно та же ошибка. Может, кто-нибудь знает, где нужно копать?
Поддерживают ли ODBC-вызовы хоть какие-то связи между таблицами? Или
дело в "нестандартности" ODBC-драйвера?
--
Best regards
(M)ike
При ответе на e-mail убрать из адреса NOS
Andrzej Novosiolov
2005-04-26 07:08:54 UTC
Permalink
Есть проект ASP.net, в котором нужно считать инфу с некой БД (находящейся
на линуксовом сервере - T-Bred, если кто в курсе) и выдать ее в виде
красивого Crystal отчета.
В стандартном виндусовом списке ODBC-драйверов нужного нету, ставим его с
сидюка фирмы.
[...]
Поддерживают ли ODBC-вызовы хоть какие-то связи между таблицами? Или дело в
"нестандартности" ODBC-драйвера?
Скорей всего, дело в нестандартности. В принципе-то ODBC может поддерживать
всё, на что способен сервер.

А если попробовать по-другому? Запросить и заполнить типизированный DataSet в
самом приложении, средствами ADO.NET, а потом передать этот готовый DataSet в
отчёт? Мы обычно так и делаем - больше простора для сложных преобразований
данных, меньше проблем с внутренними механизмами Crystal.
--
2:463/1124.5, ICQ 8481158, LJ user: andrzejn, http://surf.to/andrzej
Mike
2005-04-26 13:35:41 UTC
Permalink
Post by Andrzej Novosiolov
А если попробовать по-другому? Запросить и заполнить типизированный DataSet в
самом приложении, средствами ADO.NET, а потом передать этот готовый DataSet в
отчёт? Мы обычно так и делаем - больше простора для сложных преобразований
данных, меньше проблем с внутренними механизмами Crystal.
А как это делается? Вот так мы открываем ODBC (упрощенно, без try/catch):

OdbcConnection db1 = new OdbcConnection ();
db1.ConnectionString = "DSN=mybase;UID=user;PWD=password";
string strSQL="select * from table1, table2 where bla-bla-bla";
System.Data.DataSet dataset1=new System.Data.DataSet();
OdbcDataAdapter adapter = new OdbcDataAdapter();
adapter.SelectCommand = new OdbcCommand(strSQL, db1);
adapter.Fill(dataset1, "query");

А теперь у нас есть некий
CrystalDecisions.Web.CrystalReportViewer CrystalReportViewer1;

А как теперь присобачить к нему эту dataset1?

И главное, поскольку это происходит во время выполнения программы, как
создать для него дизайн и указать нужные поля, ведь пока программа не
запустилась, он не будет знать, какие именно поля и где их брать?
--
Best regards
(M)ike
При ответе на e-mail убрать из адреса NOS
Sergey P. Derevyago
2005-04-26 13:12:01 UTC
Permalink
Post by Mike
db1.ConnectionString = "DSN=mybase;UID=user;PWD=password";
string strSQL="select * from table1, table2 where bla-bla-bla";
System.Data.DataSet dataset1=new System.Data.DataSet();
Может дело в "select *"? Вдруг из таблиц выбираются поля с одинаковыми
именами -- Crystal мог и не знать...
Что если так:

select t1.fld1, t1.fld2,
t2.fld1
from table1 t1, table2 t2
where blya-blya-blya
--
С уважением, Сергей. http://ders.angen.net/
mailto:ders?skeptik.net
Andrzej Novosiolov
2005-04-26 13:23:16 UTC
Permalink
Post by Mike
Post by Andrzej Novosiolov
А если попробовать по-другому? Запросить и заполнить типизированный
DataSet в самом приложении, средствами ADO.NET, а потом передать этот
готовый DataSet в отчёт?
А как это делается?
Сначала нужно создать в проекте strong-typed dataset (.xsd файл с XML-схемой).
Затем при дизайне .rpt указать ему в качестве Data Source этот dataset (он
будет в секции Database Expert - Project Data - ADO.NET DataSets). Затем
(пример из рабочего ASP.NET приложения):

Dim ds As DSSummaryReport
ds = (New SummaryReportData).getSummaryReport(rp) ' rp As SummaryReportParameters
' getSummaryReport() sets command parameters and calls daSummaryReport.Fill(ds)
Dim cr As New SummaryReport
Try
cr.SetDataSource(ds)
cr.OpenSubreport("DetailsReport").SetDataSource(ds)
Dim cv As New CrystalDecisions.Shared.ParameterValues
Dim pdvName As New CrystalDecisions.Shared.ParameterDiscreteValue
pdvName.Value = rp.Name_
cv.Add(pdvEName)
cr.DataDefinition.ParameterFields("Name").ApplyCurrentValues(cv)
generatePdfReport(cr, "SummaryReport.pdf",
CrystalDecisions.[Shared].PaperSize.PaperLetter,
CrystalDecisions.[Shared].PaperOrientation.Portrait, response)
Finally
cr.Dispose()
End Try

Protected Shared Sub generatePdfReport( _
ByVal cr As CrystalDecisions.CrystalReports.Engine.ReportClass, _
ByVal reportFileName As String, _
ByVal paperSize As CrystalDecisions.[Shared].PaperSize, _
ByVal paperOrientation As CrystalDecisions.[Shared].PaperOrientation, _
ByVal response As Web.HttpResponse)
cr.PrintOptions.PaperSize = paperSize
cr.PrintOptions.PaperOrientation = paperOrientation
Dim oStm As System.IO.Stream =
cr.ExportToStream(CrystalDecisions.Shared.ExportFormatType.PortableDocFormat)
cr.Close()
Dim buffer(CInt(oStm.Length - 1)) As Byte
oStm.Read(buffer, 0, CInt(oStm.Length))
oStm.Close()
returnPdfStream(buffer, reportFileName, response)
End Sub
Post by Mike
И главное, поскольку это происходит во время выполнения программы, как
создать для него дизайн и указать нужные поля, ведь пока программа не
запустилась, он не будет знать, какие именно поля и где их брать?
Дизайн отчёта, конечно, делается заранее, поскольку в strong-typed dataset уже
указаны имена и типы полей.
--
2:463/1124.5, ICQ 8481158, LJ user: andrzejn, http://surf.to/andrzej
Loading...