using System;
using System.Data;
using System.ComponentModel;
using System.Reflection;
using System.Collections;
using FastReport.Utils;
using System.IO;
using System.Drawing.Design;
namespace FastReport.Data
{
///
/// Represents a datasource based on DataTable class.
///
/// This example shows how to add a new table to the existing connection:
///
/// Report report1;
/// DataConnectionBase conn = report1.Dictionary.Connections.FindByName("Connection1");
/// TableDataSource table = new TableDataSource();
/// table.TableName = "Employees";
/// table.Name = "Table1";
/// conn.Tables.Add(table);
///
///
public partial class TableDataSource : DataSourceBase
{
#region Fields
private DataTable table;
private string tableName;
private string selectCommand;
private CommandParameterCollection parameters;
private bool storeData;
private bool ignoreConnection;
private string qbSchema;
#endregion
#region Properties
///
/// Gets or sets the underlying DataTable object.
///
[Browsable(false)]
public DataTable Table
{
get { return table; }
set { table = value; }
}
///
/// Gets or sets the table name.
///
[Category("Data")]
public string TableName
{
get { return tableName; }
set { tableName = value; }
}
///
/// Gets or sets SQL "select" command.
///
///
/// If this command contains parameters, you should specify them in the
/// property.
///
[Category("Data")]
[Editor("FastReport.TypeEditors.SqlEditor, FastReport", typeof(UITypeEditor))]
public string SelectCommand
{
get { return selectCommand; }
set { selectCommand = value; }
}
///
/// Gets a collection of parameters used by "select" command.
///
///
/// You must set up this property if the SQL query that you've specified in the
/// property contains parameters.
/// You can pass a value to the SQL parameter in two ways.
/// The right way is to define a report parameter. You can do this in the
/// "Data" window. Once you have defined the parameter, you can use it to pass a value
/// to the SQL parameter. To do this, set the SQL parameter's Expression property
/// to the report parameter's name (so it will look like [myReportParam]).
/// To pass a value to the report parameter from your application, use the
/// method.
/// The other way (unrecommended) is to find a datasource object and set its parameter from a code:
///
/// TableDataSource ds = report.GetDataSource("My DataSource Name") as TableDataSource;
/// ds.Parameters[0].Value = 10;
///
/// This way is not good because you hardcode the report object's name.
///
[Category("Data")]
[Editor("FastReport.TypeEditors.CommandParametersEditor, FastReport", typeof(UITypeEditor))]
public CommandParameterCollection Parameters
{
get { return parameters; }
set { parameters = value; }
}
///
/// Gets or sets the parent object.
///
[Browsable(false)]
public DataConnectionBase Connection
{
get { return IgnoreConnection ? null : Parent as DataConnectionBase; }
set { Parent = value; }
}
///
/// Gets or sets a value that determines whether it is necessary to store table data in a report file.
///
[Category("Data")]
[DefaultValue(false)]
public bool StoreData
{
get { return storeData; }
set { storeData = value; }
}
///
/// Gets or sets the table data.
///
///
/// This property is for internal use only.
///
[Browsable(false)]
public virtual string TableData
{
get
{
string result = "";
if (Table == null && Connection != null)
{
Connection.CreateTable(this);
Connection.FillTable(this);
}
if (Table != null)
{
using (DataSet tempDs = new DataSet())
{
DataTable tempTable = Table.Copy();
tempDs.Tables.Add(tempTable);
using (MemoryStream stream = new MemoryStream())
{
tempDs.WriteXml(stream, XmlWriteMode.WriteSchema);
result = Convert.ToBase64String(stream.ToArray());
}
tempTable.Dispose();
}
}
return result;
}
set
{
if(!string.IsNullOrEmpty(value))
{
using (MemoryStream stream = new MemoryStream(Convert.FromBase64String(value)))
using (DataSet tempDs = new DataSet())
{
tempDs.ReadXml(stream);
table = tempDs.Tables[0];
Reference = table;
tempDs.Tables.RemoveAt(0);
}
}
}
}
///
/// If set, ignores the Connection (always returns null). Needed when we replace the
/// existing connection-based datasource with datatable defined in an application.
///
internal bool IgnoreConnection
{
get { return ignoreConnection; }
set { ignoreConnection = value; }
}
///
/// Gets or sets the query builder schema.
///
///
/// This property is for internal use only.
///
[Browsable(false)]
public string QbSchema
{
get { return qbSchema; }
set { qbSchema = value; }
}
#endregion
#region Private Methods
private Column CreateColumn(DataColumn column)
{
Column c = new Column();
c.Name = column.ColumnName;
c.Alias = column.Caption;
c.DataType = column.DataType;
c.SetBindableControlType(c.DataType);
return c;
}
private void DeleteTable()
{
if (Connection != null)
Connection.DeleteTable(this);
}
private void CreateColumns()
{
Columns.Clear();
if (Table != null)
{
foreach (DataColumn column in Table.Columns)
{
Column c = CreateColumn(column);
Columns.Add(c);
}
}
}
#endregion
#region Protected Methods
///
protected override void Dispose(bool disposing)
{
if (disposing)
DeleteTable();
base.Dispose(disposing);
}
///
protected override object GetValue(Column column)
{
if (column == null)
return null;
if (column.Tag == null)
{
int index = Table.Columns.IndexOf(column.Name);
if (index == -1)
return null;
column.Tag = index;
}
return CurrentRow == null ? null : ((DataRow)CurrentRow)[(int)column.Tag];
}
#endregion
#region Public Methods
///
public override void InitSchema()
{
if (Connection != null)
{
if (!StoreData)
{
Connection.CreateTable(this);
if (Table.Columns.Count == 0)
Connection.FillTableSchema(Table, SelectCommand, Parameters);
}
}
else
table = Reference as DataTable;
if (Columns.Count == 0)
CreateColumns();
foreach (Column column in Columns)
{
column.Tag = null;
}
}
///
public override void LoadData(ArrayList rows)
{
if (Connection != null)
{
if (!StoreData)
Connection.FillTable(this);
}
else
{
TryToLoadData();
}
if (Table == null)
throw new DataTableException(Alias);
// custom load data via Load event
OnLoad();
bool needReload = ForceLoadData || rows.Count == 0 || Parameters.Count > 0;
if (needReload)
{
// fill rows
rows.Clear();
foreach (DataRow row in Table.Rows)
{
if (row.RowState != DataRowState.Deleted && row.RowState != DataRowState.Detached)
rows.Add(row);
}
}
}
///
/// Refresh the table schema.
///
public void RefreshTable()
{
DeleteTable();
InitSchema();
RefreshColumns(true);
}
internal void RefreshColumns(bool enableNew)
{
if (Table != null)
{
// add new columns
foreach (DataColumn column in Table.Columns)
{
if (Columns.FindByName(column.ColumnName) == null)
{
Column c = CreateColumn(column);
c.Enabled = enableNew;
Columns.Add(c);
}
}
// delete obsolete columns
int i = 0;
while (i < Columns.Count)
{
Column c = Columns[i];
if (!c.Calculated && !Table.Columns.Contains(c.Name))
c.Dispose();
else
i++;
}
}
}
///
public override void Serialize(FRWriter writer)
{
base.Serialize(writer);
if (!String.IsNullOrEmpty(TableName))
writer.WriteStr("TableName", TableName);
if (!String.IsNullOrEmpty(SelectCommand))
writer.WriteStr("SelectCommand", SelectCommand);
if (!String.IsNullOrEmpty(QbSchema))
writer.WriteStr("QbSchema", QbSchema);
if (StoreData)
{
writer.WriteBool("StoreData", true);
writer.WriteStr("TableData", TableData);
}
}
///
public override void SetParent(Base value)
{
base.SetParent(value);
SetFlags(Flags.CanEdit, Connection != null);
}
///
public override void InitializeComponent()
{
base.InitializeComponent();
foreach (CommandParameter par in Parameters)
{
par.ResetLastValue();
}
}
#endregion
#region IParent Members
///
public override bool CanContain(Base child)
{
return base.CanContain(child) || child is CommandParameter;
}
///
public override void GetChildObjects(ObjectCollection list)
{
base.GetChildObjects(list);
foreach (CommandParameter p in Parameters)
{
list.Add(p);
}
}
///
public override void AddChild(Base child)
{
if (child is CommandParameter)
Parameters.Add(child as CommandParameter);
else
base.AddChild(child);
}
///
public override void RemoveChild(Base child)
{
if (child is CommandParameter)
Parameters.Remove(child as CommandParameter);
else
base.RemoveChild(child);
}
#endregion
///
/// Initializes a new instance of the class with default settings.
///
public TableDataSource()
{
TableName = "";
SelectCommand = "";
QbSchema = "";
parameters = new CommandParameterCollection(this);
}
}
}