Einzelnen Beitrag anzeigen

Elvis

Registriert seit: 25. Nov 2005
Ort: München
1.909 Beiträge
 
Delphi 2010 Professional
 
#17

Re: Merkwürdiges SELECT-Verhalten des Firebird .Net DataProv

  Alt 1. Jan 2006, 20:48
Zitat:
Search Error
Session timed out, please resubmit your search
Sorry, ich dachte die articleId wäre eine fixe referenz
Ich habe unten den ganzen Artikel nochmal im DP-style zitiert.

Zitat:
Warum sollte ich Chrome einsetzen?
Es ist einfach nur eine Klasse, die aus einer FB Datenbank ein XSDim Stile der original mitgelieferten .Net Provider generiert.
Und ich sagte nicht du _musst_ Chrome nehmen, es würde dir nur die Umwandlung zu C#/Delphi ersparen.
Zitat:
Wenn der FB .Net Data Provider dies nicht von Haus aus macht, hat er sich IMHO für mich für den praktischen Einsatz disqualifiziert.
Weder FB Provider noch BDP können typisierte DataSets anlegen, deshalb gibt es da wohl keinen Grund den FBProvider abzuwerten.
Außerdem ging das eigentlich an André, bei dem ich mir denken kann, dass es ihn interessieren könnte.

Zitat:
Zitat von Elvis:
War nur als Beispielgedacht, wie bereits erwähnt: Ich würde keinem DataSets empfehlen...
Ist hier zwar OT: Soll ich dann das Web DataGrid per Hand füllen?
Ich fände es nett, wenn Du stattdessen auf die gestellte Frage eingehen würdest.
Versuch' ich's mal...
Zitat:
Jetzt wo Du es sagst, fällt mir auf, daß gar kein xsd erzeugt wurde.
Einfach mal ein DataSet.WriteSchema an der bösen Stelle um zu sehen mit was für Constraints dein DataSet arbeitet. Zusammen mit den Daten könnte man den bösen Wert herausfinden.
Es muss ja etwas im Schema stehen, da du sonst diese Meldung nicht bekommen würdest.
Zitat:
Zitat von Elvis:
Und wenn due die Daten mal normal ausliest? Alsomit einem IDataReader und einem Container eines Value/Reference types?
Ich will diese ja direkt in einem Web-DataGrid anzeigen.
Hat auch keiner von dir verlangt.
Der kleinste gemeinsame Nenner für DataBinding an ein ListControl ist IEnumerable.
Ein Container von Instanzen eines value/reference types könnte genauso als DataSource benutzt werden wie ein IDataReader oder ein ... DataSet.

Möglich wäre als hack-around dies:
Delphi-Quellcode:
using command := DeineConnection.CreateCommand() do
begin
  command.CommandText := 'SELECT termin, ort, m1, m2, t1, t2 FROM SPIELE WHERE ART = @Gruppe';
  var parameter := command.CreateParameter();
  command.Parameters.Add(parameter);
  parameter.DbType := DbType.AnsiString;
  parameter.ParameterName := '@Gruppe';
  parameter.Value := 'A';
  
  using reader := command.ExecuteReader() do
  begin
    DeinGrid.DataSource := reader;
    DeinGrid.DataBind();
  end;
end;
Das sollte dir die Daten direkt anzeigen. Aber interessanter wäre das Schema deines DataSets, wie du es erzeugt hast und vor allem: Testdaten, die den Fehler verursachen.

Hier nochmal der Artikel hinter dem nicht funktionierenden Link...
Zitat:
Zitat:
Would anyone mind providing me with a small example of creating a dataset in code using the Firebird provider?
Hi Lee,
Problem is, that the FbProvider has this dump BDP style non-typed-DataSet
approach... :-/
I'm not a fan of DataSets, but here is some hacked-together (thus no
warranty ) code to open a Firebird database using embedded server, and
build an XSD schema from it. (Needs FbProvider and FbEmbed.dll)

The generated schema can be added to a chrome project -> ét violá.
If you have that XSD in your project: Don't forget to set the custom tool
to "MSDataSetGenerator" and build action to "None".

Hope, I could help...

Actual code:
Delphi-Quellcode:
uses
  System.Data,
  System.Data.Common,
  System.IO,
  System.Collections.Specialized,
  FirebirdSql.Data.Firebird;

type
  FirebirdXsdBuilder = public class(IDisposable)
  private
    fDatabaseFile: String;
    fDataSet: DataSet;
  protected
    method GetTableNames(connection : IDbConnection) : StringCollection;
    method BuildConnectionString : String;
    property DataSet : DataSet read fDataSet;
  public
    property DatabaseFile : String read fDatabaseFile;
    method BuildSchema;
    method Dispose;
    method WriteSchema();
    method WriteSchema(stream : Stream);
    method WriteSchema(fileName : String);
    constructor(databaseFile: String; buildSchema : Boolean := true);
 end;
  
implementation

method FirebirdXsdBuilder.GetTableNames(connection : IDbConnection) :
StringCollection;
begin
  using command := connection.CreateCommand() do
  begin
    // System tables ain't that interesting, are they? ;-)
    command.CommandText :=
      'SELECT Rdb$Relation_Name ' +
      'FROM RDB$RELATIONS ' +
      'WHERE Rdb$System_Flag = 0';
    
    result := new StringCollection();

    using reader := command.ExecuteReader() do
      while reader.Read() do
        result.Add(reader.GetString(0).Trim());
  end;
end;

method FirebirdXsdBuilder.BuildSchema;
begin
  using connection := new FbConnection(BuildConnectionString()) do
  using command := connection.CreateCommand() do
  begin
    connection.Open();
    
    var TableNames := GetTableNames(connection);
    
    if TableNames.Count > 0 then
    begin
      DataSet.Tables.Clear();

      using dataAdapter := new FbDataAdapter(command) do
      begin
        // FbProvider won't map tablenames correcty,
        // so we have to provide 'em ourself
        var tableMapping := new DataTableMapping('Table', String.Empty);

        dataAdapter.TableMappings.Add(tableMapping);

        for TableName : String in TableNames do
        begin
          // bogus select...
          command.CommandText := String.Format('SELECT * FROM {0} WHERE 1 = 2',
                                               TableName);
          // FbDataAdapter considers SourceTable always to be 'Table',
          // setting DataSetTable will change it's name in the schema
          tableMapping.DataSetTable := TableName;

          dataAdapter.MissingSchemaAction := MissingSchemaAction.AddWithKey;

          dataAdapter.Fill(DataSet);
        end;
      end;
    end;
  end;
end;

method FirebirdXsdBuilder.BuildConnectionString : String;
begin
  var connectionBuilder := new FbConnectionStringBuilder();

  // see FbProvider docs: 1 = embedded
  connectionBuilder.ServerType := 1;
  connectionBuilder.Database := DatabaseFile;

  exit(connectionBuilder.ToString());
end;

constructor FirebirdXsdBuilder(databaseFile: String; buildSchema : Boolean);
begin
  fDatabaseFile := databaseFile;
  fDataSet := new DataSet(Path.GetFileNameWithoutExtension(fDatabaseFile));
  
  if buildSchema then
    self.BuildSchema();
end;

method FirebirdXsdBuilder.WriteSchema;
begin
  DataSet.WriteXmlSchema(string.Format('{0}.xsd', DataSet.DataSetName));
end;

method FirebirdXsdBuilder.WriteSchema(stream : Stream);
begin
  DataSet.WriteXmlSchema(stream);
end;

method FirebirdXsdBuilder.WriteSchema(fileName : String);
begin
  DataSet.WriteXmlSchema(fileName);
end;

method FirebirdXsdBuilder.Dispose;
begin
  if assigned(DataSet) then
    DataSet.Dispose();
end;

It could be used like this:

Delphi-Quellcode:
class method ConsoleApp.Main(args : array of String);
begin
  if args.Length > 0 then
    using XsdBuilder := new FirebirdXsdBuilder(args[0], true) do
      XsdBuilder.WriteSchema();
end;
Robert Giesecke
  Mit Zitat antworten Zitat