Guest User

DomainService.tt

a guest
Feb 4th, 2013
133
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 13.17 KB | None | 0 0
  1. <#@ template debug="false" hostspecific="true" language="C#" #>
  2. <#@ include file="EF.Utility.CS.ttinclude"#>
  3. <#@ assembly name="System.Core" #>
  4. <#@ assembly name="System.Data.Entity" #>
  5. <#@ Assembly Name="$(SolutionDir)packages\EntityFramework.5.0.0\lib\net45\EntityFramework.dll" #>
  6. <#@ import namespace="System.Linq" #>
  7. <#@ import namespace="System.Collections.Generic" #>
  8. <#@ import namespace="System.Data.Entity.Infrastructure" #>
  9. <#@ import namespace="System.Data.Metadata.Edm" #>
  10. <#@ output extension=".cs" #><#
  11.  
  12. // settings start
  13. string inputFile = @"../../%project%.Server.Data/%project%Model.edmx";
  14. string serviceName = "%project%Service";
  15. string modelNamespace = "%namespace%";
  16. // settings end
  17.  
  18. var textTransform = DynamicTextTransformation.Create(this);
  19. var code = new CodeGenerationTools(this);
  20. var itemCollection = new EdmMetadataLoader(textTransform.Host, textTransform.Errors).CreateEdmItemCollection(inputFile);
  21.  
  22. Generate(itemCollection, code, serviceName, modelNamespace);
  23. #><#+
  24. void Generate(IEnumerable<GlobalItem> itemCollection, CodeGenerationTools code, string serviceName, string modelNamespace)
  25. {
  26.     ArgumentNotNull(itemCollection, "itemCollection");
  27.     ArgumentNotNull(code, "code");
  28.     ArgumentNotNull(serviceName, "serviceName");
  29.  
  30.     var container = itemCollection.OfType<EntityContainer>().First();
  31.     string codeNamespace = modelNamespace;//code.VsNamespaceSuggestion();
  32. #>
  33. namespace <#= code.EscapeNamespace(codeNamespace) #>
  34. {
  35.     using System.Data;
  36.     using System.Linq;
  37.     using System.ServiceModel.DomainServices.EntityFramework;
  38.     using System.ServiceModel.DomainServices.Hosting;
  39.     using System.ServiceModel.DomainServices.Server;
  40.     using System.Web.DomainServices.FluentMetadata;
  41.     using RIAServices.M2M.Configuration;
  42.     using RIAServices.M2M.DbContext;
  43. <#+
  44.     if (!string.IsNullOrEmpty(modelNamespace) && codeNamespace != modelNamespace)
  45.     {
  46. #>
  47.     using <#= code.EscapeNamespace(modelNamespace) #>;
  48. <#+
  49.     }
  50. #>
  51.  
  52.     [EnableClientAccess()]
  53.     [FluentMetadata(typeof(MetadataConfiguration))]
  54.     public partial class <#= code.Escape(serviceName) #> : DbDomainService<<#= code.Escape(container.Name) #>>
  55.     {
  56. <#+
  57.     foreach (var entitySet in container.BaseEntitySets.Where(set => set.BuiltInTypeKind == BuiltInTypeKind.EntitySet))
  58.     {
  59.         string elementName = code.Escape(entitySet.ElementType.Name);
  60.         string setName = code.Escape(entitySet.Name);
  61.         string findLine = GenerateFindLine(entitySet.ElementType);
  62. #>
  63.         [Query]
  64.         public IQueryable<<#= elementName #>> Get<#= elementName #>s()
  65.         {
  66.             return this.DbContext.<#= setName #>;
  67.         }
  68.  
  69.         [Insert]
  70.         public void Insert<#= elementName #>(<#= elementName #> entity)
  71.         {
  72.             if ((DbContext.Entry(entity).State != EntityState.Detached))
  73.             {
  74.                 this.DbContext.Entry(entity).State = EntityState.Added;
  75.             }
  76.             else
  77.             {
  78.                 this.DbContext.<#= setName #>.Add(entity);
  79.             }
  80.         }
  81.  
  82.         [Update]
  83.         public void Update<#= elementName #>(<#= elementName #> entity)
  84.         {
  85.             var local = this.DbContext.<#= setName #>.Local.FirstOrDefault(t => <#= findLine #>);
  86.             if (local == null)
  87.             {
  88.                 this.DbContext.<#= setName #>.AttachAsModified(entity, this.DbContext);
  89.             }
  90.             else
  91.             {
  92.                 this.DbContext.Entry(local).CurrentValues.SetValues(entity);
  93.                 this.DbContext.Entry(local).State = EntityState.Modified;
  94.             }
  95.         }
  96.  
  97.         [Delete]
  98.         public void Delete<#= elementName #>(<#= elementName #> entity)
  99.         {
  100.             var local = this.DbContext.<#= setName #>.Local.FirstOrDefault(t => <#= findLine #>);
  101.             if (local == null)
  102.             {
  103.                 this.DbContext.<#= setName #>.Attach(entity);
  104.                 this.DbContext.<#= setName #>.Remove(entity);
  105.             }
  106.             else
  107.             {
  108.                 this.DbContext.<#= setName #>.Remove(local);
  109.             }
  110.            
  111.         }
  112.  
  113. <#+
  114.     }
  115.    
  116.     // M2M support http://m2m4ria.codeplex.com/wikipage?title=Step-by-step%20instructions%20for%20using%20M2M%20with%20WCR%20RIA%20Services
  117.     var associations = container.BaseEntitySets
  118.         .Where(es => es.BuiltInTypeKind == BuiltInTypeKind.EntitySet)
  119.         .OfType<EntitySet>()
  120.         .SelectMany(es => es.ElementType.NavigationProperties)
  121.         .Where(np => np.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many && np.FromEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many)
  122.         .GroupBy(np => np.RelationshipType);
  123.     foreach (var propertiesGroup in associations)
  124.     {
  125.         var relationship = propertiesGroup.Key;
  126.         var className = code.Escape("M2M_" + relationship.Name);
  127.         var type1 = relationship.RelationshipEndMembers.First().GetEntityType();
  128.         var type2 = relationship.RelationshipEndMembers.Last().GetEntityType();
  129.         var basetype1 = type1;
  130.         while (basetype1.BaseType != null && basetype1.BaseType.BuiltInTypeKind == BuiltInTypeKind.EntityType)
  131.             basetype1 = (EntityType)basetype1.BaseType;
  132.         var set1 = container.BaseEntitySets
  133.             .Where(es => es.BuiltInTypeKind == BuiltInTypeKind.EntitySet)
  134.             .OfType<EntitySet>()
  135.             .First(es => es.ElementType == basetype1);
  136.         string findLine = GenerateFindLine(basetype1);
  137.         var prop1 = propertiesGroup.First(np => np.DeclaringType == type1);
  138.         var prop2 = propertiesGroup.First(np => np.DeclaringType == type2);
  139. #>
  140.         [Insert]
  141.         public void Insert<#= className #>(<#= className #> m2m_entity)
  142.         {
  143.             var entity = m2m_entity.FetchObject1(ChangeSet, DbContext);
  144.             var <#= code.Escape(type2.Name) #> = m2m_entity.FetchObject2(ChangeSet, DbContext);
  145.             if (this.DbContext.Entry(entity).State == EntityState.Detached)
  146.             {
  147.                 var local = this.DbContext.<#= code.Escape(set1.Name) #>.Local.FirstOrDefault(t => <#= findLine #>);
  148.                 if (local == null)
  149.                 {
  150.                     this.DbContext.<#= code.Escape(set1.Name) #>.Attach(entity);
  151.                 }
  152.                 else
  153.                 {
  154.                     entity = (<#= code.Escape(type1.Name) #>)local;
  155.                 }
  156.             }
  157.             entity.<#= code.Escape(prop1.Name) #>.Add(<#= code.Escape(type2.Name) #>);
  158.             DbContext.ChangeTracker.DetectChanges();
  159.         }
  160.  
  161.         [Delete]
  162.         public void Delete<#= className #>(<#= className #> m2m_entity)
  163.         {
  164.             var entity = m2m_entity.FetchObject1(ChangeSet, DbContext);
  165.             var <#= code.Escape(type2.Name) #> = m2m_entity.FetchObject2(ChangeSet, DbContext);
  166.             if (this.DbContext.Entry(entity).State == EntityState.Detached)
  167.             {
  168.                 var local = this.DbContext.<#= code.Escape(set1.Name) #>.Local.FirstOrDefault(t => <#= findLine #>);
  169.                 if (local == null)
  170.                 {
  171.                     this.DbContext.<#= code.Escape(set1.Name) #>.Attach(entity);
  172.                 }
  173.                 else
  174.                 {
  175.                     entity = (<#= code.Escape(type1.Name) #>)local;
  176.                 }
  177.             }
  178.             DbContext.LoadM2M<<#= code.Escape(type1.Name) #>, <#= code.Escape(type2.Name) #>, <#= className #>>(entity, <#= code.Escape(type2.Name) #>);
  179.             entity.<#= code.Escape(prop1.Name) #>.Remove(<#= code.Escape(type2.Name) #>);
  180.             DbContext.ChangeTracker.DetectChanges();
  181.         }
  182.  
  183. <#+
  184.     }
  185. #>
  186.     }
  187.     public class MetadataConfiguration : IFluentMetadataConfiguration
  188.     {
  189.         public void OnTypeCreation(MetadataContainer metadataContainer)
  190.         {
  191. <#+
  192.     foreach (var propertiesGroup in associations)
  193.     {
  194.         var relationship = propertiesGroup.Key;
  195.         var className = code.Escape("M2M_" + relationship.Name);
  196.         var type1 = relationship.RelationshipEndMembers.First().GetEntityType();
  197.         var type2 = relationship.RelationshipEndMembers.Last().GetEntityType();
  198.         var prop1 = propertiesGroup.First(np => np.DeclaringType == type1);
  199.         var prop2 = propertiesGroup.First(np => np.DeclaringType == type2);
  200. #>
  201.             metadataContainer.Entity<<#= code.Escape(type1.Name) #>>()
  202.                 .Projection(x => x.<#= code.Escape(prop1.Name) #>)
  203.                     .M2M(x => x.<#= className #>, x => x.<#= className #>, x => x.<#= code.Escape(prop2.Name) #>);
  204. <#+
  205.     }
  206. #>
  207.         }
  208.     }
  209. }
  210. <#+
  211. }
  212.  
  213. string GenerateFindLine(EntityTypeBase entityType)
  214. {
  215.     string findLine = "";
  216.     var last = entityType.KeyMembers.Last();
  217.     foreach (var keyMember in entityType.KeyMembers)
  218.     {
  219.         findLine += "t." + keyMember.Name + " == entity." + keyMember.Name;
  220.         if (keyMember != last)
  221.             findLine += " && ";
  222.     }
  223.     return findLine;
  224. }
  225.  
  226. public class EdmMetadataLoader
  227. {
  228.     private readonly IDynamicHost _host;
  229.     private readonly System.Collections.IList _errors;
  230.  
  231.     public EdmMetadataLoader(IDynamicHost host, System.Collections.IList errors)
  232.     {
  233.         ArgumentNotNull(host, "host");
  234.         ArgumentNotNull(errors, "errors");
  235.  
  236.         _host = host;
  237.         _errors = errors;
  238.     }
  239.  
  240.     public IEnumerable<GlobalItem> CreateEdmItemCollection(string sourcePath)
  241.     {
  242.         ArgumentNotNull(sourcePath, "sourcePath");
  243.  
  244.         if (!ValidateInputPath(sourcePath))
  245.         {
  246.             return new EdmItemCollection();
  247.         }
  248.  
  249.         var schemaElement = LoadRootElement(_host.ResolvePath(sourcePath));
  250.         if (schemaElement != null)
  251.         {
  252.             using (var reader = schemaElement.CreateReader())
  253.             {
  254.                 IList<EdmSchemaError> errors;
  255.                 var itemCollection = MetadataItemCollectionFactory.CreateEdmItemCollection(new[] { reader }, out errors);
  256.  
  257.                 ProcessErrors(errors, sourcePath);
  258.  
  259.                 return itemCollection;
  260.             }
  261.         }
  262.         return new EdmItemCollection();
  263.     }
  264.  
  265.     public string GetModelNamespace(string sourcePath)
  266.     {
  267.         ArgumentNotNull(sourcePath, "sourcePath");
  268.  
  269.         if (!ValidateInputPath(sourcePath))
  270.         {
  271.             return string.Empty;
  272.         }
  273.  
  274.         var model = LoadRootElement(_host.ResolvePath(sourcePath));
  275.         if (model == null)
  276.         {
  277.             return string.Empty;
  278.         }
  279.  
  280.         var attribute = model.Attribute("Namespace");
  281.         return attribute != null ? attribute.Value : "";
  282.     }
  283.  
  284.     private bool ValidateInputPath(string sourcePath)
  285.     {
  286.         if (sourcePath == "$" + "edmxInputFile" + "$")
  287.         {
  288.             _errors.Add(
  289.                 new CompilerError(_host.TemplateFile ?? sourcePath, 0, 0, string.Empty,
  290.                     GetResourceString("Template_ReplaceVsItemTemplateToken")));
  291.             return false;
  292.         }
  293.  
  294.         return true;
  295.     }
  296.  
  297.     public XElement LoadRootElement(string sourcePath)
  298.     {
  299.         ArgumentNotNull(sourcePath, "sourcePath");
  300.  
  301.         var root = XElement.Load(sourcePath, LoadOptions.SetBaseUri | LoadOptions.SetLineInfo);
  302.         return root.Elements()
  303.             .Where(e => e.Name.LocalName == "Runtime")
  304.             .Elements()
  305.             .Where(e => e.Name.LocalName == "ConceptualModels")
  306.             .Elements()
  307.             .Where(e => e.Name.LocalName == "Schema")
  308.             .FirstOrDefault()
  309.                 ?? root;
  310.     }
  311.  
  312.     private void ProcessErrors(IEnumerable<EdmSchemaError> errors, string sourceFilePath)
  313.     {
  314.         foreach (var error in errors)
  315.         {
  316.             _errors.Add(
  317.                 new CompilerError(
  318.                     error.SchemaLocation ?? sourceFilePath,
  319.                     error.Line,
  320.                     error.Column,
  321.                     error.ErrorCode.ToString(CultureInfo.InvariantCulture),
  322.                     error.Message)
  323.                 {
  324.                     IsWarning = error.Severity == EdmSchemaErrorSeverity.Warning
  325.                 });
  326.         }
  327.     }
  328.    
  329.     public bool IsLazyLoadingEnabled(EntityContainer container)
  330.     {
  331.         string lazyLoadingAttributeValue;
  332.         var lazyLoadingAttributeName = MetadataConstants.EDM_ANNOTATION_09_02 + ":LazyLoadingEnabled";
  333.         bool isLazyLoading;
  334.         return !MetadataTools.TryGetStringMetadataPropertySetting(container, lazyLoadingAttributeName, out lazyLoadingAttributeValue)
  335.             || !bool.TryParse(lazyLoadingAttributeValue, out isLazyLoading)
  336.             || isLazyLoading;
  337.     }
  338. }
  339.  
  340. public static void ArgumentNotNull<T>(T arg, string name) where T : class
  341. {
  342.     if (arg == null)
  343.     {
  344.         throw new ArgumentNullException(name);
  345.     }
  346. }
  347.  
  348. private static readonly Lazy<System.Resources.ResourceManager> ResourceManager =
  349.     new Lazy<System.Resources.ResourceManager>(
  350.         () => new System.Resources.ResourceManager("System.Data.Entity.Design", typeof(MetadataItemCollectionFactory).Assembly), isThreadSafe: true);
  351.  
  352. public static string GetResourceString(string resourceName)
  353. {
  354.     ArgumentNotNull(resourceName, "resourceName");
  355.  
  356.     return ResourceManager.Value.GetString(resourceName, null);
  357. }
  358. #>
Advertisement
Add Comment
Please, Sign In to add comment