Appendix B. Technical FAQ
How is the type of an enumeration item implicitly determined by the engine in template expressions?
If you do not specify the type of an enumeration item in a foreach
statement or lambda function signature within your template explicitly, the type is implicitly determined by the engine from the type of the enumeration as follows:
- If the enumeration represents a
DataTable
instance, then the item type isDataRow
. - Otherwise, if the enumeration represents a
DataView
instance, then the item type isDataRowView
. - Otherwise, if the enumeration implements
IDataReader
, then the item type isIDataRecord
. - Otherwise, if the enumeration represents child rows of a
DataRow
instance, then the item type isDataRow
. - Otherwise, if the enumeration implements generic
IEnumerable<T>
, then the item type is a type argument corresponding to T. Note, that the engine does not support enumerations that implementIEnumerable<T>
multiple times using different type arguments. - Otherwise, the item type is
Object
.
Does the engine cooperate with LINQ providers?
The engine does not cooperate with LINQ providers. To be aware of the consequences of this feature, consider the following example. Assume, that you have the City
and Person
classes defined in your application as follows.
public class City
{
public IList<Person> Persons { get { ... } }
...
}
public class Person
{
public String Name { get { ... } }
public int Age { get { ... } }
...
}
}
Given that city
is an instance of the City
class, consider the evaluation of the following template expression by the engine.
city.Persons.Where(p => p.Age > 30).OrderBy(p => p.Name)
If you use an ORM to provide an interaction of your application with an SQL database in conjunction with a LINQ provider for the ORM, then you most likely expect an SQL query like the following one to be performed in the background while evaluating the template expression.
SELECT *
FROM Persons
WHERE CityId = @CityId AND Age > 30
ORDER BY Name
However, since the engine does not cooperate with LINQ providers, the actual SQL query in this case is as follows.
SELECT *
FROM Persons
WHERE CityId = @CityId
That is, the engine makes an eager call before applying its built-in extension methods. In some cases, this feature can lead to a significant performance overhead. So, if the performance of your application is your primary concern, then consider a preparing of your sequential data outside your templates. That is, pass to the engine a sequential data that is already filtered, ordered, grouped, and so forth.
Have I do something special to merge the Aspose.Words assembly with another assembly?
You can normally use a tool like ILMerge to merge the Aspose.Words assembly with another assembly. However, if you use a functionality of the LINQ Reporting Engine, add the following attribute to the target assembly.
[assembly: InternalsVisibleTo(
"TargetAssemblyName" +
".ReportingDynamics" +
", PublicKey=TargetAssemblyPublicKey")]
TargetAssemblyName
and TargetAssemblyPublicKey
stand for the name of your target assembly and its public key (not a public key token) respectively.
Despite of the InternalsVisibleTo
attribute applied, you can normally use obfuscation routines on your target assembly, if needed. An obfuscation does not harm the functionality of LINQ Reporting Engine.