zengcheng / codesmith

Automatically exported from code.google.com/p/codesmith
0 stars 0 forks source link

Changing IMultipleResult generated classes name #500

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
It is known that Plinqo supports stored procedures with several select 
statements inside. The problem is those autogenerated classes have name as 
"MethodName" + "Result" + IncrementedNumber  and when there are many classes it 
is not clear which class what means. It would be clearer to have custom names 
for such classes to easily distinguish them. I tried to inherit those classes 
and call stored procedures using inherited versions but got that such 
workaround requires some manipulations with those classes.

Let me explain the problem with following example.

Suppose we have generated with Plinqo following method to call stored procedure 
which has 4 select statements inside

 [System.Data.Linq.Mapping.Function(Name="dbo.ComplexSp_Get")]
 [System.Data.Linq.Mapping.ResultType(typeof(MyProject.ComplexSpGetResult1))]
 [System.Data.Linq.Mapping.ResultType(typeof(MyProject.ComplexSpGetResult2))]
 [System.Data.Linq.Mapping.ResultType(typeof(MyProject.ComplexSpGetResult3))]
 [System.Data.Linq.Mapping.ResultType(typeof(MyProject.ComplexSpGetResult4))]
 [System.CodeDom.Compiler.GeneratedCode("CodeSmith", "5.0.0.0")]
 public System.Data.Linq.IMultipleResults ComplexSpGet(
    [System.Data.Linq.Mapping.Parameter(Name="@Id", DbType="int")] int? Id)
 {
    var methodInfo = (System.Reflection.MethodInfo)System.Reflection.MethodInfo.GetCurrentMethod();
    var result = this.ExecuteMethodCall(this, methodInfo, Id);

    return ((System.Data.Linq.IMultipleResults)(result.ReturnValue));
 }
And how to call that:
var r = Db.ComplexSpGet( id );
var _main = _model.GetResult<ComplexSpGetResult1> ().FirstOrDefault ();
var _products = _model.GetResult<ComplexSpGetResult2> ().ToList ();
var _orders = _model.GetResult<ComplexSpGetResult3> ().ToList ();
var _relatedobjects = _model.GetResult<ComplexSpGetResult4> ().ToList ();
Fine

but I think it would be better to use custom names of classes 
(ComplexSpGet_Main, ComplexSpGetResult_Products, ComplexSpGetResult_Orders...)  
instead of
(ComplexSpGetResult1, ComplexSpGetResult2...) 

var _main = _model.GetResult<ComplexSpGetResult_Main> ().FirstOrDefault ();
var _products = _model.GetResult<ComplexSpGetResult_Product> ().ToList ();
var _orders = _model.GetResult<ComplexSpGetResult_Order> ().ToList ();
var _relatedobjects = _model.GetResult<ComplexSpGetResult_RelatedObject> 
().ToList ();

The easiest way is to use copy/past for ComplexSpGetResult* classes into new 
classes and set respective names for them. But each time when select statements 
in stored procedure will be changed we need to manually repeat copy/paste 
operations for each of those classes. And if there are several such stored 
procedures that that could be very annoying operation. So in that way we loose 
our very important advantage of code automatic updating.

The templates would need to be updated  to support this. But I think each 
result would need to match a specific result set or we would need a way to 
define this in the DBML file if you can't already define a name for it. This 
way if result set 2 changes we could rename it accordingly.

See 
http://community.codesmithtools.com/Template_Frameworks/f/66/p/11339/43373.aspx#
43373

Original issue reported on code.google.com by gusen...@gmail.com on 16 Sep 2010 at 12:51

GoogleCodeExporter commented 9 years ago

Original comment by paul.wel...@gmail.com on 20 Sep 2010 at 5:37

GoogleCodeExporter commented 9 years ago
Recently I played a bit with your templates and get it worked. That required 
changing single template file - CSharp\Entities.cst

You need to make 3 simple steps for that:
1. Add to properties in that file:

<%@ Assembly Name="CodeSmith.CustomProperties" %>

<%@ Import Namespace="CodeSmith.CustomProperties" %>

<%@ Property Category="1.Mapping" Name="CustomResultsMapping"
Type="CodeSmith.CustomProperties.NameValueCollection" Optional="True"
Description="List of pairs (original class name and its desired replacement)"
  Default="ComplexSpResult1=ComplexSpResult_Main" %>

2. Somewhere between <script></script> tags:
// look for "CustomResultsMapping" and "SetMappingClassNames" usage in this file
private string GetMappingClassName(string className){
  var value = CustomResultsMapping.GetByKey(className);
  return value ?? className; 
}

private void SetMappingClassNames(Database database){
  if (CustomResultsMapping != null) {
   foreach (var fn in database.Functions){
     foreach (var tp in fn.Types){
       tp.Name = GetMappingClassName(tp.Name);
       foreach (var stp in tp.SubTypes)
         stp.Name = GetMappingClassName(stp.Name); 
     }
   }
  }
}

3. Change CreateDataContextClass method as following:

public void CreateDataContextClass(Database database)
{
    var t = this.Create<DataContextGeneratedClass>();
    this.CopyPropertiesTo( t );
    SetMappingClassNames( database );
    t.Database = database;
    //... rest of method code here
}

That's all. Manage template - add as keys class names you want to change and as 
values class names you want to be generated instead.

As a result classes with new names will be generated. Also new class name will 
be passed as method attributes.

I've attached also result file here.
Thanks a ton for plinqo!

Original comment by gusen...@gmail.com on 24 Sep 2010 at 8:23

Attachments: