Build Reports using LINQ Reporting | Using IDataRecord IDataReader Hierarchical Data | Master Detail Relation C#

The code.zip download doesn’t work. Where is the sample? @awais.hafeez

@IT2BE,

Please try using the following code:

DocumentBuilder builder = new DocumentBuilder();
builder.Writeln("<<foreach [in persons]>>Person: <<[Name]>>");
builder.Writeln("<<foreach [in items]>>  - <<[Item]>>");
builder.Writeln("<</foreach>>");
builder.Writeln("<</foreach>>");

// Initialize data sources.
DataReader reader = new DataReader();
DetailDataReader detailReader = new DetailDataReader(reader, 0);

// Build a report.
ReportingEngine engine = new ReportingEngine();
engine.BuildReport(builder.Document, new object[] { reader, detailReader }, new string[] { "persons", "items" });

// Print the report's content.
Console.WriteLine(builder.Document.ToString(SaveFormat.Text));

internal struct ExampleEntity
{
    internal int Id;
    internal string Name;
}

public class DataReader : IDataReader
{
    public int FieldCount
    {
        get { return 2; }
    }

    public bool Read()
    {
        // In this example, we simply enumerate an array in a data reader fashion.
        // In a real-life application, the next entity should be read by this method.
        if (mCurrentIndex == mExampleEntities.Length - 1)
            return false;

        mCurrentIndex++;
        return true;
    }

    public Type GetFieldType(int i)
    {
        switch (i)
        {
            case 0:
                return typeof(int);
            case 1:
                return typeof(string);
            default:
                throw new ArgumentOutOfRangeException("i");
        }
    }

    public string GetName(int i)
    {
        switch (i)
        {
            case 0:
                return "Id";
            case 1:
                return "Name";
            default:
                throw new ArgumentOutOfRangeException("i");
        }
    }

    public object GetValue(int i)
    {
        if (mCurrentIndex < 0)
            throw new InvalidOperationException();

        switch (i)
        {
            case 0:
                return mExampleEntities[mCurrentIndex].Id;
            case 1:
                return mExampleEntities[mCurrentIndex].Name;
            default:
                throw new ArgumentOutOfRangeException("i");
        }
    }

    private readonly ExampleEntity[] mExampleEntities = new ExampleEntity[]
    {
            new ExampleEntity { Id = 1, Name = "John Doe" },
            new ExampleEntity { Id = 2, Name = "Jane Doe" },
            new ExampleEntity { Id = 3, Name = "John Smith" },
    };

    private int mCurrentIndex = -1;

    // The following members are not used by Reporting Engine, so we leave them as not implemented.
    #region Not implemented members

    public void Close()
    {
        throw new NotImplementedException();
    }

    public int Depth
    {
        get { throw new NotImplementedException(); }
    }

    public DataTable GetSchemaTable()
    {
        throw new NotImplementedException();
    }

    public bool IsClosed
    {
        get { throw new NotImplementedException(); }
    }

    public bool NextResult()
    {
        throw new NotImplementedException();
    }

    public int RecordsAffected
    {
        get { throw new NotImplementedException(); }
    }

    public void Dispose()
    {
        throw new NotImplementedException();
    }

    public bool GetBoolean(int i)
    {
        throw new NotImplementedException();
    }

    public byte GetByte(int i)
    {
        throw new NotImplementedException();
    }

    public long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length)
    {
        throw new NotImplementedException();
    }

    public char GetChar(int i)
    {
        throw new NotImplementedException();
    }

    public long GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length)
    {
        throw new NotImplementedException();
    }

    public IDataReader GetData(int i)
    {
        throw new NotImplementedException();
    }

    public string GetDataTypeName(int i)
    {
        throw new NotImplementedException();
    }

    public DateTime GetDateTime(int i)
    {
        throw new NotImplementedException();
    }

    public decimal GetDecimal(int i)
    {
        throw new NotImplementedException();
    }

    public double GetDouble(int i)
    {
        throw new NotImplementedException();
    }

    public float GetFloat(int i)
    {
        throw new NotImplementedException();
    }

    public Guid GetGuid(int i)
    {
        throw new NotImplementedException();
    }

    public short GetInt16(int i)
    {
        throw new NotImplementedException();
    }

    public int GetInt32(int i)
    {
        throw new NotImplementedException();
    }

    public long GetInt64(int i)
    {
        throw new NotImplementedException();
    }

    public int GetOrdinal(string name)
    {
        throw new NotImplementedException();
    }

    public string GetString(int i)
    {
        throw new NotImplementedException();
    }

    public int GetValues(object[] values)
    {
        throw new NotImplementedException();
    }

    public bool IsDBNull(int i)
    {
        throw new NotImplementedException();
    }

    public object this[string name]
    {
        get { throw new NotImplementedException(); }
    }

    public object this[int i]
    {
        get { throw new NotImplementedException(); }
    }

    #endregion
}

public class DetailDataReader : IDataReader
{
    public DetailDataReader(DataReader parent, int parentIdFieldIndex)
    {
        mParent = parent;
        mParentIdFieldIndex = parentIdFieldIndex;
    }

    public int FieldCount
    {
        get { return 1; }
    }

    public bool Read()
    {
        // In this example, we simply enumerate an array in a data reader fashion.
        // In a real-life application, the next entity should be read by this method.
        if (mCurrentIndex == CurrentItems.Length - 1)
            return false;

        mCurrentIndex++;
        return true;
    }

    public Type GetFieldType(int i)
    {
        switch (i)
        {
            case 0:
                return typeof(string);
            default:
                throw new ArgumentOutOfRangeException("i");
        }
    }

    public string GetName(int i)
    {
        switch (i)
        {
            case 0:
                return "Item";
            default:
                throw new ArgumentOutOfRangeException("i");
        }
    }

    public object GetValue(int i)
    {
        if (mCurrentIndex < 0)
            throw new InvalidOperationException();

        switch (i)
        {
            case 0:
                return CurrentItems[mCurrentIndex];
            default:
                throw new ArgumentOutOfRangeException("i");
        }
    }

    private string[] FetchItems()
    {
        switch (mCurrentParentId)
        {
            case 1:
                return new string[] { "Item1", "Item2" };
            case 2:
                return new string[] { "Item3" };
            case 3:
                return new string[] { "Item4", "Item5", "Item6" };
            default:
                return null;
        }
    }

    private string[] CurrentItems
    {
        get
        {
            int parentId = (int)mParent.GetValue(mParentIdFieldIndex);
            if (mCurrentParentId != parentId)
            {
                mCurrentParentId = parentId;
                mCurrentItems = FetchItems();
                mCurrentIndex = -1;
            }

            return mCurrentItems;
        }
    }

    private readonly DataReader mParent;
    private readonly int mParentIdFieldIndex;
    private int mCurrentIndex = -1;
    private int mCurrentParentId = -1;
    private string[] mCurrentItems;

    // The following members are not used by Reporting Engine, so we leave them as not implemented.
    #region Not implemented members

    public void Close()
    {
        throw new NotImplementedException();
    }

    public int Depth
    {
        get { throw new NotImplementedException(); }
    }

    public DataTable GetSchemaTable()
    {
        throw new NotImplementedException();
    }

    public bool IsClosed
    {
        get { throw new NotImplementedException(); }
    }

    public bool NextResult()
    {
        throw new NotImplementedException();
    }

    public int RecordsAffected
    {
        get { throw new NotImplementedException(); }
    }

    public void Dispose()
    {
        throw new NotImplementedException();
    }

    public bool GetBoolean(int i)
    {
        throw new NotImplementedException();
    }

    public byte GetByte(int i)
    {
        throw new NotImplementedException();
    }

    public long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length)
    {
        throw new NotImplementedException();
    }

    public char GetChar(int i)
    {
        throw new NotImplementedException();
    }

    public long GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length)
    {
        throw new NotImplementedException();
    }

    public IDataReader GetData(int i)
    {
        throw new NotImplementedException();
    }

    public string GetDataTypeName(int i)
    {
        throw new NotImplementedException();
    }

    public DateTime GetDateTime(int i)
    {
        throw new NotImplementedException();
    }

    public decimal GetDecimal(int i)
    {
        throw new NotImplementedException();
    }

    public double GetDouble(int i)
    {
        throw new NotImplementedException();
    }

    public float GetFloat(int i)
    {
        throw new NotImplementedException();
    }

    public Guid GetGuid(int i)
    {
        throw new NotImplementedException();
    }

    public short GetInt16(int i)
    {
        throw new NotImplementedException();
    }

    public int GetInt32(int i)
    {
        throw new NotImplementedException();
    }

    public long GetInt64(int i)
    {
        throw new NotImplementedException();
    }

    public int GetOrdinal(string name)
    {
        throw new NotImplementedException();
    }

    public string GetString(int i)
    {
        throw new NotImplementedException();
    }

    public int GetValues(object[] values)
    {
        throw new NotImplementedException();
    }

    public bool IsDBNull(int i)
    {
        throw new NotImplementedException();
    }

    public object this[string name]
    {
        get { throw new NotImplementedException(); }
    }

    public object this[int i]
    {
        get { throw new NotImplementedException(); }
    }

    #endregion
}