I am in the process of making my own very basic ORM and I am stuck. Right now I am trying to build a collection of my model classes from a datareader and I have it partially working. From what I have read you don't want to use reflection a lot as it is slow so I found this article: http://www.codeproject.com/Articles/...ion-techniques which suggets using Linq to dynamically build a new constructor for my model classes.
After a lot of headache converting C# to VB and removing the bits I didn't think I needed I ended up with this:
I don't have a very strong grasp on what exactly is going on with this as it seems pretty foreign. I have a general idea of what it is doing, building a custom delegate that accepts a datareader and outputs an entity (my base class for all my custom data models) It basically assumes a 1 to 1 association of the column name in the database to the property name in my class. The issue I am having is when I have a dbnull value in my database it cant cast to to my propertytype. So somewhere in the for each loop I am guessing I need to modify the expression to be more explicit in converting.
Like I said, I am completely new to linq and these expressions so I am still reading up on this but I don't know if it is even possible to have a conditional expression so I thought I would post this. Any help would be greatly appreciated!
After a lot of headache converting C# to VB and removing the bits I didn't think I needed I ended up with this:
Code:
Public Function GetReader() As Func(Of OleDbDataReader, Entity)
Dim resDelegate As [Delegate]
Dim body As BlockExpression
Dim lambda As LambdaExpression
Dim argtype(0) As Type
argtype(0) = "".GetType()
Dim statements As New List(Of Expression) 'List of statements in our dynamic method
Dim indexerProperty As PropertyInfo = GetType(OleDbDataReader).GetProperty("Item", argtype) 'Get the indexer property of the DataReader
Dim instanceParam As ParameterExpression = Expression.Variable(GetType(T)) 'Instance type of target entity class
Dim readerParam As ParameterExpression = Expression.Parameter(GetType(OleDbDataReader)) 'Parameter for the SqlDataReader object
Dim createInstance As BinaryExpression = Expression.Assign(instanceParam, Expression.[New](GetType(T)))
statements.Add(createInstance)
Dim propertyCol As New List(Of Expression)
For Each prop As PropertyInfo In GetType(T).GetProperties()
If IsNothing(GetType(T).BaseType.GetProperty(prop.Name)) Then
Dim getProperty As MemberExpression = Expression.Property(instanceParam, prop)
Dim readValue As IndexExpression = Expression.MakeIndex(readerParam, indexerProperty, New Expression() {Expression.Constant(prop.Name)})
Dim assignProperty As BinaryExpression = Expression.Assign(getProperty, Expression.Convert(readValue, prop.PropertyType))
statements.Add(assignProperty)
End If
Next
Dim returnStatement = instanceParam
statements.Add(returnStatement)
body = Expression.Block(instanceParam.Type, {instanceParam}, statements.ToArray())
lambda = Expression.Lambda(Of Func(Of OleDbDataReader, T))(body, readerParam)
resDelegate = lambda.Compile()
Return DirectCast(resDelegate, Func(Of OleDbDataReader, Entity))
End Function
I don't have a very strong grasp on what exactly is going on with this as it seems pretty foreign. I have a general idea of what it is doing, building a custom delegate that accepts a datareader and outputs an entity (my base class for all my custom data models) It basically assumes a 1 to 1 association of the column name in the database to the property name in my class. The issue I am having is when I have a dbnull value in my database it cant cast to to my propertytype. So somewhere in the for each loop I am guessing I need to modify the expression to be more explicit in converting.
Like I said, I am completely new to linq and these expressions so I am still reading up on this but I don't know if it is even possible to have a conditional expression so I thought I would post this. Any help would be greatly appreciated!