Amazing extension function CopyLinqDataMembersByName to expand Linq-to-SQL.
I think Linq-To-SQL is great framework, if you don't plan use another server than MS SQL. And I continue extend I think Linq-To-SQL is great framework, if you don't plan use another server than MS SQL. Therefore I been continue extend this framework with new functions. Some my extensions I had described in page Five amazing Linq-to-SQL extension. In this page I will tell about my new amazing extension. But first of all I describing an environment where this extension is absolutely must.
In three screenshot below you may see absolutely common pattern of ASP.NET programming.
- In first screen we may see a request to DB by Linq-to-SQL
- In second screen we may see a control databinding to list of record
- In there screed we may see a repiter, that included ASP.NET control
This is most common template of ASP.NET programming and using Linq-to-SQL. And generally not need anything another to write code inside ASP.NET control.
But this approach has a big problem, first of it that one item of construction, that return Linq-to-SQL not be a serialized and not be stored to Viewstate.
And I have second big problem - in my project I have big existing control (with more than 500 strings of code), and I don't want to change all this code, I want to create small path over this code. Historically this control had working with stupid construction like in screen below.
And previous programmer of this project bind this control to DataRow, that he produced with big list of DataSet (XSD-files).
If he loading XSD-result to control's repiter dataset, he does not another way than construction like dtProddetails.Rows(i).Item("ProductId") or DabinderEval like in screenshot above.
I don't want to learn carefully existing 530 string of code, I want to change DataSet-framework to Linq-to-SQL framework and I search a way to simple transform stupid construction from untyped dataset with string name with parentheses of fields to typed Linq-to-SQL name of fields. And second problem for refactoring of this code is permanently changing DB fields name, therefore I want to statically fix some names, what need to working control correctly.
For solve this problem, I found this solution.
- Collect fields name from existing control code and create class DropShipTrunc, based in that names.
- After that I simple automatically transfrom control code from construction DataRow("FieldName") to construction CurrentRow.FieldName, when CurrenRow is class DropShipTrunc
- Write Linq-To-SQL Extension function to create simple serialized class DropShipTrunc, that may be stored to ViewState and in this class I fixed fields name in Db, what need to work control correctly.
If you can read my article for this place, you are ready to understand simple thing - no way alternative to function below.
So, this is my amazing function to expand Linq-to-SQL world.
1: Imports Microsoft.VisualBasic
2:
3: Public Module Extension4
4:
5: <Runtime.CompilerServices.Extension()> _
6: Public Function CopyLinqDataMembersByName(Of targetClass)(dc As Data.Linq.DataContext, sourceEntity As Object, targetEntity As targetClass) As targetClass
7:
8: Dim SourceMembers As IEnumerable(Of Data.Linq.Mapping.MetaDataMember) = _
9: From SourceOne In dc.Mapping.GetTable(sourceEntity.[GetType]()).RowType.DataMembers Select SourceOne Where SourceOne.IsAssociation = False
10:
11: For Each SourceOne As Data.Linq.Mapping.MetaDataMember In SourceMembers
12: For Each TargetOne In targetEntity.GetType().GetFields()
13:
14: If TargetOne.Name = SourceOne.Name Then
15: Dim SourcePropInfo As System.Reflection.PropertyInfo = sourceEntity.[GetType]().GetProperty(SourceOne.Name)
16: TargetOne.SetValue(targetEntity, SourcePropInfo.GetValue(sourceEntity, Nothing))
17: Exit For
18: End If
19:
20: Next
21: Next
22: Return targetEntity
23: End Function
24: End Module
And below you may see how to execute this function:
I hope you understanding how I transform nonserialized dynamically type that return Linq-to-SQL to statically type with the same name, that may be stored in Viewstate and names of this type is needed for control working.
Also in passing for this solution I avoided to rebuild big strange control. And my most important goal for this refactoring - I was be able to rebuild this fragment of site from untyped dataset to more useful Linq-to-SQL. All these goals I could get by creating this amazing Linq-to-SQL extension.
And there is public universal package to do the same work Use AutoMapper to create projection (View) from POCO classes.