Example of Nested Mail Merge using LINQ SQL

Hi,

do you have an example of doing a nested mail merge using LINQ SQL ?

thanks

Pete

Hi
Thanks for your request. I created a simple code example using LINQ to XML to demonstrate the technique. You can use the same technique with LINQ to SQL:

[Test]
public void Test001()
{
    // Load XML document
    XDocument ordersXml = XDocument.Load(@"Test001\data.xml");
    var query = from order in ordersXml.Descendants("order")
                select new
                {
                    id = (string)order.Attribute("id"),
                    description = (string)order.Attribute("desc"),
                    items = (from item in order.Descendants("item")
                             where (string)item.Attribute("oredrid") == (string)order.Attribute("id")
                             select new
                             {
                                 name = (string)item.Attribute("name"),
                                 price = (string)item.Attribute("price"),
                                 amount = (string)item.Attribute("amount")
                             })
                };
    // Create a custom mail merge data source from the LINQ query results
    MailMergeDataSource ordersDataSource = new MailMergeDataSource(query, "orders");
    // Open template and execute mail merge with regions.
    Document doc = new Document(@"Test001\in.doc");
    doc.MailMerge.ExecuteWithRegions(ordersDataSource);
    doc.Save(@"Test001\out.doc");
}
///
/// A custom mail merge data source that you implement to allow Aspose.Words
/// to mail merge data from LINQ query results into Microsoft Word documents.
///
public class MailMergeDataSource: IMailMergeDataSource
{
    ///
    /// Creates new instance of a custom mail merge data source
    ///
    /// Data returned from a LINQ query
    public MailMergeDataSource(IEnumerable data)
    {
        mEnumerator = data.GetEnumerator();
    }
    ///
    /// Creates new instance of a custom mail merge data source
    ///
    /// Data returned from a LINQ query
    /// Name of the data source is only used when you perform mail merge with regions.
    /// If you would like to use simple mail merge then use constructor with one parameter.
    public MailMergeDataSource(IEnumerable data, string tableName)
    {
        mEnumerator = data.GetEnumerator();
        // Name of the data source is needed when you perform mail merge with regions
        mTableName = tableName;
    }
    ///
    /// Aspose.Words call this to get a value for every data field.
    ///
    public bool GetValue(string fieldName, out object fieldValue)
    {
        fieldValue = GetPropertyValue(fieldName);
        return (fieldValue != null);
    }
    ///
    /// Aspose.Words calls this method when nested regions is encountered.
    ///
    public IMailMergeDataSource GetChildDataSource(string tableName)
    {
        // If property contains enumerable data we will returr mail merge datasource for these data.
        object nestedData = GetPropertyValue(tableName);
        if (nestedData is IEnumerable)
            return new MailMergeDataSource((IEnumerable) nestedData);
        return null;
    }
    ///
    /// Moves to the next record in the collection.
    ///
    public bool MoveNext()
    {
        // Move enumerator to next record
        bool hasNexeRecord = mEnumerator.MoveNext();
        if (hasNexeRecord)
            mCurrentObject = mEnumerator.Current;
        return hasNexeRecord;
    }
    ///
    /// The name of the data source. Used by Aspose.Words only when executing mail merge with repeatable regions.
    ///
    public string TableName
    {
        get
        {
            return mTableName;
        }
    }
    private object GetPropertyValue(string propertyName)
    {
        object propertyValue = null;
        // Get type of current record
        Type curentRecordType = mCurrentObject.GetType();
        // Use reflection to get property by name and its value
        PropertyInfo property = curentRecordType.GetProperty(propertyName);
        if (property != null)
            propertyValue = property.GetValue(mCurrentObject, null) ?? string.Empty;
        return propertyValue;
    }
    private IEnumerator mEnumerator;
    private object mCurrentObject;
    private string mTableName = string.Empty;
}

Hope this helps. Please let me know if you need more assistance, I will be glad to help you.
Best regards,

Many thanks Alexey!

Pete