Esempio n. 1
0
        public ProjectFeature CreateProjectFeature(string projectId, ProjectFeature projectFeature)
        {
            var writer =
                new JsonWriter(
                    new DataWriterSettings(new JsonResolverStrategy()));
            var data = writer.Write(projectFeature);

            return(m_caller.PostFormat <ProjectFeature>(data, HttpContentTypes.ApplicationJson,
                                                        HttpContentTypes.ApplicationJson, "/app/rest/projects/id:{0}/projectFeatures",
                                                        projectId));
        }
        private static MethodDefinition GetGetMethod(ProjectFeature <EntityFrameworkCoreProjectSettings> projectFeature, ProjectSelection <EntityFrameworkCoreProjectSettings> projectSelection, ITable table)
        {
            var project = projectFeature.GetEntityFrameworkCoreProject();

            var expression = string.Empty;

            if (table.Identity == null)
            {
                expression = string.Format("item => {0}", string.Join(" && ", table.PrimaryKey.Key.Select(item => string.Format("item.{0} == entity.{0}", project.CodeNamingConvention.GetPropertyName(item)))));
            }
            else
            {
                expression = string.Format("item => item.{0} == entity.{0}", project.CodeNamingConvention.GetPropertyName(table.Identity.Name));
            }

            if (projectSelection.Settings.EntitiesWithDataContracts)
            {
                var lines = new List <ILine>
                {
                    new CodeLine("return await DbContext.{0}", project.GetDbSetPropertyName(table))
                };

                foreach (var foreignKey in table.ForeignKeys)
                {
                    var foreignTable = project.Database.FindTable(foreignKey.References);

                    if (foreignKey == null)
                    {
                        continue;
                    }

                    lines.Add(new CodeLine(1, ".Include(p => p.{0})", foreignKey.GetParentNavigationProperty(foreignTable, project).Name));
                }

                lines.Add(new CodeLine(1, ".FirstOrDefaultAsync({0});", expression));

                return(new MethodDefinition(AccessModifier.Public, string.Format("Task<{0}>", project.GetEntityName(table)), project.GetGetRepositoryMethodName(table), new ParameterDefinition(project.GetEntityName(table), "entity"))
                {
                    IsAsync = true,
                    Lines = lines
                });
            }
            else
            {
                return(new MethodDefinition(AccessModifier.Public, string.Format("Task<{0}>", project.GetEntityName(table)), project.GetGetRepositoryMethodName(table), new ParameterDefinition(project.GetEntityName(table), "entity"))
                {
                    IsAsync = true,
                    Lines =
                    {
                        new CodeLine("return await DbContext.{0}.FirstOrDefaultAsync({1});", project.GetDbSetPropertyName(table), expression)
                    }
                });
            }
        }
Esempio n. 3
0
        private static MethodDefinition GetGetMethod(ProjectFeature projectFeature, ITable table)
        {
            var entityFrameworkCoreProject = projectFeature.GetEntityFrameworkCoreProject();

            var expression = string.Empty;

            if (table.Identity == null)
            {
                expression = string.Format("item => {0}", string.Join(" && ", table.PrimaryKey.Key.Select(item => string.Format("item.{0} == entity.{0}", NamingExtensions.namingConvention.GetPropertyName(item)))));
            }
            else
            {
                expression = string.Format("item => item.{0} == entity.{0}", NamingExtensions.namingConvention.GetPropertyName(table.Identity.Name));
            }

            if (entityFrameworkCoreProject.Settings.EntitiesWithDataContracts.Contains(table.FullName))
            {
                var lines = new List <ILine>
                {
                    new CodeLine("return await DbContext.{0}", entityFrameworkCoreProject.Settings.DeclareDbSetPropertiesInDbContext ? table.GetPluralName() : string.Format("Set<{0}>()", table.GetSingularName()))
                };

                foreach (var foreignKey in table.ForeignKeys)
                {
                    var foreignTable = projectFeature.Project.Database.FindTableByFullName(foreignKey.References);

                    if (foreignKey == null)
                    {
                        continue;
                    }

                    lines.Add(new CodeLine(1, ".Include(p => p.{0})", foreignKey.GetParentNavigationProperty(entityFrameworkCoreProject, foreignTable).Name));
                }

                lines.Add(new CodeLine(1, ".FirstOrDefaultAsync({0});", expression));

                return(new MethodDefinition(string.Format("Task<{0}>", table.GetSingularName()), table.GetGetRepositoryMethodName(), new ParameterDefinition(table.GetSingularName(), "entity"))
                {
                    IsAsync = true,
                    Lines = lines
                });
            }
            else
            {
                return(new MethodDefinition(string.Format("Task<{0}>", table.GetSingularName()), table.GetGetRepositoryMethodName(), new ParameterDefinition(table.GetSingularName(), "entity"))
                {
                    IsAsync = true,
                    Lines = new List <ILine>
                    {
                        new CodeLine("return await DbContext.{0}.FirstOrDefaultAsync({1});", entityFrameworkCoreProject.Settings.DeclareDbSetPropertiesInDbContext ? table.GetPluralName() : string.Format("Set<{0}>()", table.GetSingularName()), expression)
                    }
                });
            }
        }
Esempio n. 4
0
        private static void GetGetAllMethod(this CSharpClassDefinition definition, ProjectFeature <EntityFrameworkCoreProjectSettings> projectFeature, IView view)
        {
            var efCoreProject = projectFeature.GetEntityFrameworkCoreProject();

            definition.Methods.Add(new MethodDefinition(string.Format("IQueryable<{0}>", efCoreProject.GetEntityName(view)), efCoreProject.GetGetAllRepositoryMethodName(view))
            {
                Lines =
                {
                    new CodeLine("return DbContext.{0};", efCoreProject.GetDbSetPropertyName(view))
                }
            });
        }
Esempio n. 5
0
 public ActionResult Edit([Bind(Include = "ProjectFeatureID,ProjectID,PropertyID")] ProjectFeature projectFeature)
 {
     if (ModelState.IsValid)
     {
         db.Entry(projectFeature).State = EntityState.Modified;
         db.SaveChanges();
         return(RedirectToAction("Index"));
     }
     ViewBag.ProjectID  = new SelectList(db.Projects, "ProjectID", "name", projectFeature.ProjectID);
     ViewBag.PropertyID = new SelectList(db.Properties, "PropertyID", "Property1", projectFeature.PropertyID);
     return(View(projectFeature));
 }
        private static MethodDefinition GetGetAllMethodWithoutForeigns(ProjectFeature <EntityFrameworkCoreProjectSettings> projectFeature, ProjectSelection <EntityFrameworkCoreProjectSettings> projectSelection, ITable table)
        {
            var project = projectFeature.GetEntityFrameworkCoreProject();

            return(new MethodDefinition(AccessModifier.Public, string.Format("IQueryable<{0}>", project.GetEntityName(table)), project.GetGetAllRepositoryMethodName(table))
            {
                Lines =
                {
                    new CodeLine("return DbContext.{0};", project.GetDbSetPropertyName(table))
                }
            });
        }
Esempio n. 7
0
        private static MethodDefinition GetGetAllMethod(ProjectFeature <EntityFrameworkCoreProjectSettings> projectFeature, StoredProcedure storedProcedure)
        {
            var project = projectFeature.GetEntityFrameworkCoreProject();

            var parameters = new List <ParameterDefinition>();

            var lines = new List <ILine>()
            {
                new CommentLine(" Create query for table function")
            };

            lines.Add(new CodeLine("var query = new"));
            lines.Add(new CodeLine("{"));
            lines.Add(new CodeLine(1, "Text = \" exec {0} {1} \",", project.Database.GetFullName(storedProcedure), string.Join(", ", storedProcedure.Parameters.Select(item => item.Name))));

            if (storedProcedure.Parameters.Count == 0)
            {
                lines.Add(new CodeLine(1, "Parameters = new object[] {}"));
            }
            else
            {
                lines.Add(new CodeLine(1, "Parameters = new[]"));
                lines.Add(new CodeLine(1, "{"));

                foreach (var parameter in storedProcedure.Parameters)
                {
                    lines.Add(new CodeLine(2, "new SqlParameter(\"{0}\", {1}),", parameter.Name, project.CodeNamingConvention.GetParameterName(parameter.Name)));

                    parameters.Add(new ParameterDefinition(project.Database.ResolveDatabaseType(parameter), project.CodeNamingConvention.GetParameterName(parameter.Name)));
                }

                lines.Add(new CodeLine(1, "}"));
            }

            lines.Add(new CodeLine("};"));

            lines.Add(new EmptyLine());

            lines.Add(new ReturnLine("await DbContext"));
            lines.Add(new CodeLine(1, ".Query<{0}>()", project.GetEntityResultName(storedProcedure)));
            lines.Add(new CodeLine(1, ".FromSql(query.Text, query.Parameters)"));
            lines.Add(new CodeLine(1, ".ToListAsync();"));

            return(new MethodDefinition
            {
                AccessModifier = AccessModifier.Public,
                IsAsync = true,
                Type = string.Format("Task<IEnumerable<{0}>>", project.GetEntityResultName(storedProcedure)),
                Name = project.GetGetAllRepositoryMethodName(storedProcedure),
                Parameters = parameters,
                Lines = lines
            });
        }
        private static MethodDefinition GetByUniqueMethod(ProjectFeature <DapperProjectSettings> projectFeature, ITable table, Unique unique)
        {
            var lines = new List <ILine>();

            lines.Add(new CommentLine(" Create connection instance"));
            lines.Add(new CodeLine("using (var connection = new SqlConnection(ConnectionString))"));
            lines.Add(new CodeLine("{"));
            lines.Add(new CommentLine(1, " Create string builder for query"));
            lines.Add(new CodeLine(1, "var query = new StringBuilder();"));
            lines.Add(new CodeLine());
            lines.Add(new CommentLine(1, " Create sql statement"));
            lines.Add(new CodeLine(1, "query.Append(\" select \");"));

            for (var i = 0; i < table.Columns.Count; i++)
            {
                var column = table.Columns[i];

                lines.Add(new CodeLine(1, "query.Append(\"  {0}{1} \");", column.GetColumnName(), i < table.Columns.Count - 1 ? "," : string.Empty));
            }

            lines.Add(new CodeLine(1, "query.Append(\" from \");"));
            lines.Add(new CodeLine(1, "query.Append(\"  {0} \");", table.GetFullName()));

            lines.Add(new CodeLine(1, "query.Append(\" where \");"));

            if (table.PrimaryKey != null && table.PrimaryKey.Key.Count == 1)
            {
                var column = table.GetColumnsFromConstraint(unique).First();

                lines.Add(new CodeLine(1, "query.Append(\"  {0} = {1} \");", column.GetColumnName(), column.GetSqlServerParameterName()));
                lines.Add(new CodeLine());

                lines.Add(new CommentLine(1, " Create parameters collection"));
                lines.Add(new CodeLine(1, "var parameters = new DynamicParameters();"));
                lines.Add(new CodeLine());

                lines.Add(new CodeLine(1, "parameters.Add(\"{0}\", entity.{1});", column.GetParameterName(), column.GetPropertyName()));
                lines.Add(new CodeLine());

                lines.Add(new CommentLine(1, " Retrieve result from database and convert to entity class"));
                lines.Add(new CodeLine(1, "return await connection.QueryFirstOrDefaultAsync<{0}>(query.ToString(), parameters);", table.GetEntityName()));
                lines.Add(new CodeLine("}"));
            }

            return(new MethodDefinition(string.Format("Task<{0}>", table.GetEntityName()), table.GetGetByUniqueRepositoryMethodName(unique), new ParameterDefinition(table.GetEntityName(), "entity"))
            {
                IsAsync = true,
                Lines = lines
            });
        }
Esempio n. 9
0
        // GET: ProjectFeatures/Details/5
        public ActionResult Details(int?id)
        {
            if (id == null)
            {
                return(new HttpStatusCodeResult(HttpStatusCode.BadRequest));
            }
            ProjectFeature projectFeature = db.ProjectFeatures.Find(id);

            if (projectFeature == null)
            {
                return(HttpNotFound());
            }
            return(View(projectFeature));
        }
Esempio n. 10
0
        static void A()
        {
            // Import database
            var factory = new SqlServerDatabaseFactory()
            {
                ConnectionString = key
            };
            var database = factory.Import();
            // Create instance of Entity Framework Core Project
            var entityFrameworkProject = new EntityFrameworkCoreProject()
            {
                Name            = "OnLineStore.Core",
                Database        = database,
                OutputDirectory = @"./"
            };

            // Apply settings for project
            entityFrameworkProject.GlobalSelection(settings => {
                settings.ForceOverwrite   = true;
                settings.ConcurrencyToken = "Timestamp";
                settings.AuditEntity      = new AuditEntity {
                    CreationUserColumnName       = "CreationUser",
                    CreationDateTimeColumnName   = "CreationDateTime",
                    LastUpdateUserColumnName     = "LastUpdateUser",
                    LastUpdateDateTimeColumnName = "LastUpdateDateTime"
                };
            });

            entityFrameworkProject.Select("dbo.Orders", settings => settings.EntitiesWithDataContracts = true);

            // Build features for project, group all entities by schema into a feature
            entityFrameworkProject.BuildFeatures();

            // Scaffolding =^^=
            entityFrameworkProject
            .ScaffoldEntityLayer()
            .ScaffoldDataLayer();

            var aspNetCoreProject = entityFrameworkProject
                                    .CreateAspNetCoreProject("Northwind.WebAPI", @"./", entityFrameworkProject.Database);

            aspNetCoreProject.GlobalSelection(settings => {
                settings.ForceOverwrite = true;
            });
            var se = new ProjectFeature <AspNetCoreProjectSettings>();

            aspNetCoreProject.AddFeature(se);
            aspNetCoreProject.ScaffoldAspNetCore();
        }
        public async Task <IActionResult> OnGetAsync(Guid?id)
        {
            if (id == null)
            {
                return(NotFound());
            }

            ProjectFeature = await _context.ProjectFeature.FirstOrDefaultAsync(m => m.Id == id);

            if (ProjectFeature == null)
            {
                return(NotFound());
            }
            return(Page());
        }
Esempio n. 12
0
 private static MethodDefinition GetRemoveMethod(ProjectFeature projectFeature, ITable table)
 {
     return(new MethodDefinition("Task<Int32>", table.GetRemoveRepositoryMethodName(), new ParameterDefinition(table.GetSingularName(), "entity"))
     {
         IsAsync = true,
         Lines = new List <ILine>
         {
             new CommentLine(" Remove entity from DbSet"),
             new CodeLine("Remove(entity);"),
             new CodeLine(),
             new CommentLine(" Save changes through DbContext"),
             new CodeLine("return await CommitChangesAsync();")
         }
     });
 }
Esempio n. 13
0
        private static MethodDefinition GetGetByUniqueMethods(ProjectFeature projectFeature, ITable table, Unique unique)
        {
            var entityFrameworkCoreProject = projectFeature.GetEntityFrameworkCoreProject();

            var expression = string.Format("item => {0}", string.Join(" && ", unique.Key.Select(item => string.Format("item.{0} == entity.{0}", NamingExtensions.namingConvention.GetPropertyName(item)))));

            return(new MethodDefinition(string.Format("Task<{0}>", table.GetSingularName()), table.GetGetByUniqueRepositoryMethodName(unique), new ParameterDefinition(table.GetSingularName(), "entity"))
            {
                IsAsync = true,
                Lines = new List <ILine>
                {
                    new CodeLine("return await DbContext.{0}.FirstOrDefaultAsync({1});", entityFrameworkCoreProject.Settings.DeclareDbSetPropertiesInDbContext ? table.GetPluralName() : string.Format("Set<{0}>()", table.GetSingularName()), expression)
                }
            });
        }
Esempio n. 14
0
        // GET: ProjectFeatures/Edit/5
        public ActionResult Edit(int?id)
        {
            if (id == null)
            {
                return(new HttpStatusCodeResult(HttpStatusCode.BadRequest));
            }
            ProjectFeature projectFeature = db.ProjectFeatures.Find(id);

            if (projectFeature == null)
            {
                return(HttpNotFound());
            }
            ViewBag.ProjectID  = new SelectList(db.Projects, "ProjectID", "name", projectFeature.ProjectID);
            ViewBag.PropertyID = new SelectList(db.Properties, "PropertyID", "Property1", projectFeature.PropertyID);
            return(View(projectFeature));
        }
Esempio n. 15
0
        private static MethodDefinition GetUpdateMethod(ProjectFeature projectFeature, ITable table)
        {
            var lines = new List <ILine>();

            lines.Add(new CommentLine(" Update entity in DbSet"));
            lines.Add(new CodeLine("Update(changes);"));
            lines.Add(new CodeLine());
            lines.Add(new CommentLine(" Save changes through DbContext"));
            lines.Add(new CodeLine("return await CommitChangesAsync();"));

            return(new MethodDefinition("Task<Int32>", table.GetUpdateRepositoryMethodName(), new ParameterDefinition(table.GetSingularName(), "changes"))
            {
                IsAsync = true,
                Lines = lines
            });
        }
Esempio n. 16
0
        private static MethodDefinition GetGetByUniqueMethods(ProjectFeature <EntityFrameworkCoreProjectSettings> projectFeature, ITable table, Unique unique)
        {
            var efCoreProject = projectFeature.GetEntityFrameworkCoreProject();

            var selection = efCoreProject.GetSelection(table);

            var expression = string.Format("item => {0}", string.Join(" && ", unique.Key.Select(item => string.Format("item.{0} == entity.{0}", efCoreProject.CodeNamingConvention.GetPropertyName(item)))));

            return(new MethodDefinition(string.Format("Task<{0}>", efCoreProject.GetEntityName(table)), efCoreProject.GetGetByUniqueRepositoryMethodName(table, unique), new ParameterDefinition(efCoreProject.GetEntityName(table), "entity"))
            {
                IsAsync = true,
                Lines =
                {
                    new CodeLine("return await DbContext.{0}.FirstOrDefaultAsync({1});", efCoreProject.GetDbSetPropertyName(table), expression)
                }
            });
        }
Esempio n. 17
0
        public void it_returns_projectFeatures_field()
        {
            string projectId = "_Root";
            string featureId = "PROJECT_EXT_1";

            PropertyField       propertyField       = PropertyField.WithFields(name: true, value: true, inherited: true);
            PropertiesField     propertiesField     = PropertiesField.WithFields(propertyField: propertyField);
            ProjectFeatureField projectFeatureField = ProjectFeatureField.WithFields(type: true, properties: propertiesField);

            ProjectFeature projectFeature = m_client.Projects.GetFields(projectFeatureField.ToString()).GetProjectFeatureByProjectFeature(projectId, featureId);

            Assert.That(projectFeature != null, "No project feature found for that specific project");
            Assert.That(projectFeature.Type != null, "Bad Value type");
            Assert.That(projectFeature.Properties != null, "Bad Value type");
            Assert.That(projectFeature.Href == null, "Bad Value type");
            Assert.That(projectFeature.Id == null, "Bad Value type");
        }
Esempio n. 18
0
        public async Task <IActionResult> OnPostAsync(Guid?id)
        {
            if (id == null)
            {
                return(NotFound());
            }

            ProjectFeature = await _context.ProjectFeature.FindAsync(id);

            if (ProjectFeature != null)
            {
                _context.ProjectFeature.Remove(ProjectFeature);
                await _context.SaveChangesAsync();
            }

            return(RedirectToPage("./Index"));
        }
Esempio n. 19
0
        private static MethodDefinition GetGetAllMethodWithoutForeigns(ProjectFeature <EntityFrameworkCoreProjectSettings> projectFeature, ProjectSelection <EntityFrameworkCoreProjectSettings> projectSelection, ITable table)
        {
            var project = projectFeature.GetEntityFrameworkCoreProject();

            var existingViews = project.Database.Views.Count(item => item.Name == table.Name);

            var genericTypeName = existingViews == 0 ? project.GetEntityName(table) : project.GetFullEntityName(table);
            var dbSetName       = existingViews == 0 ? project.GetDbSetPropertyName(table) : project.GetFullDbSetPropertyName(table);

            return(new MethodDefinition
            {
                AccessModifier = AccessModifier.Public,
                Type = string.Format("IQueryable<{0}>", genericTypeName),
                Name = project.GetGetAllRepositoryMethodName(table),
                Lines =
                {
                    new CodeLine("return DbContext.{0};", dbSetName)
                }
            });
        }
Esempio n. 20
0
        public void it_refuses_projectFeatures_create_modify_delete_when_unauthorized()
        {
            string         projectId = "_Root";
            ProjectFeature pf        = new ProjectFeature
            {
                Id         = "Test_TTT",
                Type       = "ReportTab",
                Properties = new Properties
                {
                    Property = new List <Property>
                    {
                        new Property {
                            Name = "startPage", Value = "javadoc.zip!index.html"
                        },
                        new Property {
                            Name = "title", Value = "javadoc.zip!index.html"
                        },
                        new Property {
                            Name = "type", Value = "BuildReportTab"
                        },
                    }
                }
            };


            try
            {
                ProjectFeature projectFeature = m_client.Projects.CreateProjectFeature(projectId, pf);
                m_client.Projects.DeleteProjectFeature(projectId, projectFeature.Id);
            }
            catch (HttpException e)
            {
                Assert.That(e.ResponseStatusCode == HttpStatusCode.Forbidden,
                            "Creating a project feature should fail with unauthorized http exception.");
            }
            catch (Exception e)
            {
                Assert.Fail("Create project feature raised an expected exception", e);
            }
        }
Esempio n. 21
0
        private static MethodDefinition GetAddMethod(ProjectFeature projectFeature, ITable table)
        {
            var lines = new List <ILine>();

            if (table.IsPrimaryKeyGuid())
            {
                lines.Add(new CommentLine(" Set value for GUID"));
                lines.Add(new CodeLine("entity.{0} = Guid.NewGuid();", NamingExtensions.namingConvention.GetPropertyName(table.PrimaryKey.Key[0])));
                lines.Add(new CodeLine());
            }

            lines.Add(new CommentLine(" Add entity in DbSet"));
            lines.Add(new CodeLine("Add(entity);"));
            lines.Add(new CodeLine());
            lines.Add(new CommentLine(" Save changes through DbContext"));
            lines.Add(new CodeLine("return await CommitChangesAsync();"));

            return(new MethodDefinition("Task<Int32>", table.GetAddRepositoryMethodName(), new ParameterDefinition(table.GetSingularName(), "entity"))
            {
                IsAsync = true,
                Lines = lines
            });
        }
Esempio n. 22
0
        public static IEnumerable <Column> GetUpdateColumns(this ProjectFeature <AspNetCoreProjectSettings> projectFeature, ITable table)
        {
            var settings = projectFeature.GetAspNetCoreProject().GetSelection(table).Settings;

            foreach (var column in table.Columns)
            {
                if (table.PrimaryKey != null && table.PrimaryKey.Key.Contains(column.Name))
                {
                    continue;
                }

                if (settings.AuditEntity != null && settings.AuditEntity.Names.Contains(column.Name))
                {
                    continue;
                }

                if (!string.IsNullOrEmpty(settings.ConcurrencyToken) && string.Compare(settings.ConcurrencyToken, column.Name) == 0)
                {
                    continue;
                }

                yield return(column);
            }
        }
        private static MethodDefinition GetGetAllMethod(ProjectFeature <DapperProjectSettings> projectFeature, ITable table)
        {
            var lines = new List <ILine>();

            lines.Add(new CommentLine(" Create connection instance"));
            lines.Add(new CodeLine("using (var connection = new SqlConnection(ConnectionString))"));
            lines.Add(new CodeLine("{"));

            var selection = projectFeature.GetDapperProject().GetSelection(table);

            var filters = table.ForeignKeys.Count > 0 || selection.Settings.AddPagingForGetAllOperations ? true : false;

            if (selection.Settings.UseStringBuilderForQueries)
            {
                lines.Add(new CommentLine(1, " Create string builder for query"));
                lines.Add(new CodeLine(1, "var query = new StringBuilder();"));
                lines.Add(new CodeLine());
                lines.Add(new CommentLine(1, " Create sql statement"));
                lines.Add(new CodeLine(1, "query.Append(\" select \");"));

                for (var i = 0; i < table.Columns.Count; i++)
                {
                    var column = table.Columns[i];

                    lines.Add(new CodeLine(1, "query.Append(\"  {0}{1} \");", column.GetColumnName(), i < table.Columns.Count - 1 ? "," : string.Empty));
                }

                lines.Add(new CodeLine(1, "query.Append(\" from \");"));
                lines.Add(new CodeLine(1, "query.Append(\"  {0} \");", table.GetFullName()));

                if (filters)
                {
                    lines.Add(new CodeLine(1, "query.Append(\" where \");"));

                    for (var i = 0; i < table.ForeignKeys.Count; i++)
                    {
                        var foreignKey = table.ForeignKeys[i];

                        if (foreignKey.Key.Count == 1)
                        {
                            var column = table.GetColumnsFromConstraint(foreignKey).ToList().First();

                            lines.Add(new CodeLine(1, "query.Append(\"  ({0} is null or {1} = {0}) {2} \");", column.GetSqlServerParameterName(), column.GetColumnName(), i < table.ForeignKeys.Count - 1 ? "and" : string.Empty));
                        }
                    }
                }

                if (selection.Settings.AddPagingForGetAllOperations)
                {
                    lines.Add(new CodeLine(1, "query.Append(\" order by \");"));

                    lines.Add(new CodeLine(1, "query.Append(\" {0} \");", table.Columns.First().GetColumnName()));

                    lines.Add(new CodeLine(1, "query.Append(\" offset @pageSize * (@pageNumber - 1) rows \");"));
                    lines.Add(new CodeLine(1, "query.Append(\" fetch next @pageSize rows only \");"));
                }
            }
            else
            {
                lines.Add(new CommentLine(1, " Create sql statement"));

                lines.Add(new CodeLine(1, "var query = @\""));
                lines.Add(new CodeLine(1, " select "));

                for (var i = 0; i < table.Columns.Count; i++)
                {
                    var column = table.Columns[i];

                    lines.Add(new CodeLine(1, "  {0}{1} ", column.GetColumnName(), i < table.Columns.Count - 1 ? "," : string.Empty));
                }

                lines.Add(new CodeLine(1, " from "));
                lines.Add(new CodeLine(1, "  {0} ", table.GetFullName()));

                if (filters)
                {
                    if (table.ForeignKeys.Count > 0)
                    {
                        lines.Add(new CodeLine(1, " where "));

                        for (var i = 0; i < table.ForeignKeys.Count; i++)
                        {
                            var foreignKey = table.ForeignKeys[i];

                            if (foreignKey.Key.Count == 1)
                            {
                                var column = table.GetColumnsFromConstraint(foreignKey).ToList().First();

                                lines.Add(new CodeLine(1, "  ({0} is null or {1} = {0}) {2} ", column.GetSqlServerParameterName(), column.GetColumnName(), i < table.ForeignKeys.Count - 1 ? "and" : string.Empty));
                            }
                        }
                    }
                }

                if (selection.Settings.AddPagingForGetAllOperations)
                {
                    lines.Add(new CodeLine(1, " order by "));

                    lines.Add(new CodeLine(1, " {0} ", table.Columns.First().GetColumnName()));

                    lines.Add(new CodeLine(1, " offset @pageSize * (@pageNumber - 1) rows "));
                    lines.Add(new CodeLine(1, " fetch next @pageSize rows only "));
                }

                lines.Add(new CodeLine(1, " \";"));
            }

            lines.Add(new CodeLine());

            if (filters)
            {
                lines.Add(new CommentLine(1, " Create parameters collection"));
                lines.Add(new CodeLine(1, "var parameters = new DynamicParameters();"));
                lines.Add(new CodeLine());

                lines.Add(new CommentLine(1, " Add parameters to collection"));

                if (selection.Settings.AddPagingForGetAllOperations)
                {
                    lines.Add(new CodeLine(1, "parameters.Add(\"@pageSize\", pageSize);"));
                    lines.Add(new CodeLine(1, "parameters.Add(\"@pageNumber\", pageNumber);"));
                }

                foreach (var foreignKey in table.ForeignKeys)
                {
                    var column = table.GetColumnsFromConstraint(foreignKey).ToList().First();

                    lines.Add(new CodeLine(1, "parameters.Add(\"{0}\", {1});", column.GetSqlServerParameterName(), column.GetParameterName()));
                }

                lines.Add(new CodeLine());
            }

            lines.Add(new CommentLine(1, " Retrieve result from database and convert to typed list"));

            if (filters)
            {
                lines.Add(new CodeLine(1, "return await connection.QueryAsync<{0}>(new CommandDefinition(query.ToString(), parameters));", table.GetEntityName()));
            }
            else
            {
                lines.Add(new CodeLine(1, "return await connection.QueryAsync<{0}>(query.ToString());", table.GetEntityName()));
            };

            lines.Add(new CodeLine("}"));

            var parameters = new List <ParameterDefinition>();

            if (filters)
            {
                if (selection.Settings.AddPagingForGetAllOperations)
                {
                    parameters.Add(new ParameterDefinition("Int32", "pageSize")
                    {
                        DefaultValue = "10"
                    });
                    parameters.Add(new ParameterDefinition("Int32", "pageNumber")
                    {
                        DefaultValue = "1"
                    });
                }

                foreach (var foreignKey in table.ForeignKeys)
                {
                    // todo: add logic to retrieve multiple columns from foreign key
                    var column = table.GetColumnsFromConstraint(foreignKey).ToList().First();

                    parameters.Add(new ParameterDefinition(projectFeature.Project.Database.ResolveType(column), column.GetParameterName())
                    {
                        DefaultValue = "null"
                    });
                }
            }

            return(new MethodDefinition(string.Format("Task<IEnumerable<{0}>>", table.GetEntityName()), table.GetGetAllRepositoryMethodName(), parameters.ToArray())
            {
                IsAsync = true,
                Lines = lines
            });
        }
        private static MethodDefinition GetAddMethod(ProjectFeature <DapperProjectSettings> projectFeature, Table table)
        {
            var lines = new List <ILine>();

            if (projectFeature.Project.Database.PrimaryKeyIsGuid(table))
            {
                lines.Add(new CommentLine(" Generate value for Guid property"));
                lines.Add(new CodeLine("entity.{0} = Guid.NewGuid();", table.GetColumnsFromConstraint(table.PrimaryKey).First().GetPropertyName()));
                lines.Add(new CodeLine());
            }

            lines.Add(new CommentLine(" Create connection instance"));
            lines.Add(new CodeLine("using (var connection = new SqlConnection(ConnectionString))"));
            lines.Add(new CodeLine("{"));

            var insertColumns = projectFeature.GetDapperProject().GetInsertColumns(table).ToList();

            var selection = projectFeature.GetDapperProject().GetSelection(table);

            if (selection.Settings.UseStringBuilderForQueries)
            {
                lines.Add(new CommentLine(1, " Create string builder for query"));
                lines.Add(new CodeLine(1, "var query = new StringBuilder();"));
                lines.Add(new CodeLine());
                lines.Add(new CommentLine(1, " Create sql statement"));
                lines.Add(new CodeLine(1, "query.Append(\" insert into \");"));
                lines.Add(new CodeLine(1, "query.Append(\"  {0} \");", table.GetFullName()));
                lines.Add(new CodeLine(1, "query.Append(\"  ( \");"));

                for (var i = 0; i < insertColumns.Count(); i++)
                {
                    var column = insertColumns[i];

                    lines.Add(new CodeLine(1, "query.Append(\"   {0}{1} \");", column.GetColumnName(), i < insertColumns.Count - 1 ? "," : string.Empty));
                }

                lines.Add(new CodeLine(1, "query.Append(\"  ) \");"));
                lines.Add(new CodeLine(1, "query.Append(\" values \");"));
                lines.Add(new CodeLine(1, "query.Append(\" ( \");"));

                for (var i = 0; i < insertColumns.Count(); i++)
                {
                    var column = insertColumns[i];

                    lines.Add(new CodeLine(1, "query.Append(\"  {0}{1} \");", column.GetSqlServerParameterName(), i < insertColumns.Count - 1 ? "," : string.Empty));
                }

                lines.Add(new CodeLine(1, "query.Append(\" ) \");"));

                if (table.Identity != null)
                {
                    var identityColumn = table.GetIdentityColumn();

                    lines.Add(new CodeLine(1, "query.Append(\"  select {0} = @@identity \");", identityColumn.GetSqlServerParameterName()));
                }
            }
            else
            {
                lines.Add(new CommentLine(1, " Create sql statement"));
                lines.Add(new CodeLine(1, "var query = @\" insert into "));
                lines.Add(new CodeLine(1, "  {0} ", table.GetFullName()));
                lines.Add(new CodeLine(1, "  ( "));

                for (var i = 0; i < insertColumns.Count(); i++)
                {
                    var column = insertColumns[i];

                    lines.Add(new CodeLine(1, "   {0}{1} ", column.GetColumnName(), i < insertColumns.Count - 1 ? "," : string.Empty));
                }

                lines.Add(new CodeLine(1, "  ) "));
                lines.Add(new CodeLine(1, " values "));
                lines.Add(new CodeLine(1, " ( "));

                for (var i = 0; i < insertColumns.Count(); i++)
                {
                    var column = insertColumns[i];

                    lines.Add(new CodeLine(1, "  {0}{1} ", column.GetSqlServerParameterName(), i < insertColumns.Count - 1 ? "," : string.Empty));
                }

                lines.Add(new CodeLine(1, " ) "));

                if (table.Identity != null)
                {
                    var identityColumn = table.GetIdentityColumn();

                    lines.Add(new CodeLine(1, "  select {0} = @@identity ", identityColumn.GetSqlServerParameterName()));
                }

                lines.Add(new CodeLine(1, " \";"));
            }

            lines.Add(new CodeLine());

            lines.Add(new CommentLine(1, " Create parameters collection"));
            lines.Add(new CodeLine(1, "var parameters = new DynamicParameters();"));

            lines.Add(new CodeLine());
            lines.Add(new CommentLine(1, " Add parameters to collection"));

            if (table.Identity == null)
            {
                for (var i = 0; i < insertColumns.Count; i++)
                {
                    var column = insertColumns[i];

                    lines.Add(new CodeLine(1, "parameters.Add(\"{0}\", entity.{1});", column.GetParameterName(), column.GetPropertyName()));
                }

                lines.Add(new CodeLine());
                lines.Add(new CommentLine(1, " Execute query in database"));
                lines.Add(new CodeLine(1, "return await connection.ExecuteAsync(new CommandDefinition(query.ToString(), parameters));"));

                lines.Add(new CodeLine("}"));
            }
            else
            {
                for (var i = 0; i < insertColumns.Count; i++)
                {
                    var column = insertColumns[i];

                    lines.Add(new CodeLine(1, "parameters.Add(\"{0}\", entity.{1});", column.GetParameterName(), column.GetPropertyName()));
                }

                var identityColumn = table.GetIdentityColumn();

                lines.Add(new CodeLine(1, "parameters.Add(\"{0}\", dbType: {1}, direction: ParameterDirection.Output);", identityColumn.GetParameterName(), projectFeature.Project.Database.ResolveDbType(identityColumn)));

                lines.Add(new CodeLine());
                lines.Add(new CommentLine(1, " Execute query in database"));
                lines.Add(new CodeLine(1, "var affectedRows = await connection.ExecuteAsync(new CommandDefinition(query.ToString(), parameters));"));
                lines.Add(new CodeLine());

                lines.Add(new CommentLine(1, " Retrieve value for output parameters"));
                lines.Add(new CodeLine(1, "entity.{0} = parameters.Get<{1}>(\"{2}\");", identityColumn.GetPropertyName(), projectFeature.Project.Database.ResolveType(identityColumn), identityColumn.GetParameterName()));
                lines.Add(new CodeLine());

                lines.Add(new CodeLine(1, "return affectedRows;"));

                lines.Add(new CodeLine("}"));
            }

            return(new MethodDefinition("Task<Int32>", table.GetAddRepositoryMethodName(), new ParameterDefinition(table.GetEntityName(), "entity"))
            {
                IsAsync = true,
                Lines = lines
            });
        }
        private static MethodDefinition GetRemoveMethod(ProjectFeature <DapperProjectSettings> projectFeature, Table table)
        {
            var lines = new List <ILine>();

            lines.Add(new CommentLine(" Create connection instance"));
            lines.Add(new CodeLine("using (var connection = new SqlConnection(ConnectionString))"));
            lines.Add(new CodeLine("{"));

            var keyColumns = table.GetColumnsFromConstraint(table.PrimaryKey).ToList();

            var selection = projectFeature.GetDapperProject().GetSelection(table);

            if (selection.Settings.UseStringBuilderForQueries)
            {
                lines.Add(new CommentLine(1, " Create string builder for query"));
                lines.Add(new CodeLine(1, "var query = new StringBuilder();"));
                lines.Add(new CodeLine());
                lines.Add(new CommentLine(1, " Create sql statement"));
                lines.Add(new CodeLine(1, "query.Append(\" delete from \");"));
                lines.Add(new CodeLine(1, "query.Append(\"  {0} \");", table.GetFullName()));
                lines.Add(new CodeLine(1, "query.Append(\" where \");"));

                for (var i = 0; i < keyColumns.Count; i++)
                {
                    var column = keyColumns[i];

                    lines.Add(new CodeLine(1, "query.Append(\"  {0} = {1}{2} \");", column.GetColumnName(), column.GetSqlServerParameterName(), i < keyColumns.Count - 1 ? " and " : string.Empty));
                }
            }
            else
            {
                lines.Add(new CommentLine(1, " Create sql statement"));
                lines.Add(new CodeLine(1, "var query = @\" delete from "));
                lines.Add(new CodeLine(1, "  {0} ", table.GetFullName()));
                lines.Add(new CodeLine(1, " where "));

                for (var i = 0; i < keyColumns.Count; i++)
                {
                    var column = keyColumns[i];

                    lines.Add(new CodeLine(1, "  {0} = {1}{2} ", column.GetColumnName(), column.GetSqlServerParameterName(), i < keyColumns.Count - 1 ? " and " : string.Empty));
                }

                lines.Add(new CodeLine(1, " \"; "));
            }

            lines.Add(new CodeLine());

            lines.Add(new CommentLine(1, " Create parameters collection"));
            lines.Add(new CodeLine(1, "var parameters = new DynamicParameters();"));

            lines.Add(new CodeLine());
            lines.Add(new CommentLine(1, " Add parameters to collection"));

            var columns = table.GetColumnsFromConstraint(table.PrimaryKey).ToList();

            for (var i = 0; i < columns.Count(); i++)
            {
                var column = columns[i];

                lines.Add(new CodeLine(1, "parameters.Add(\"{0}\", entity.{1});", column.GetParameterName(), column.GetPropertyName()));
            }

            lines.Add(new CodeLine());
            lines.Add(new CommentLine(1, " Execute query in database"));
            lines.Add(new CodeLine(1, "return await connection.ExecuteAsync(new CommandDefinition(query.ToString(), parameters));"));

            lines.Add(new CodeLine("}"));

            return(new MethodDefinition("Task<Int32>", table.GetDeleteRepositoryMethodName(), new ParameterDefinition(table.GetEntityName(), "entity"))
            {
                IsAsync = true,
                Lines = lines
            });
        }
        private static MethodDefinition GetGetAllMethod(ProjectFeature <AspNetCoreProjectSettings> projectFeature, CSharpClassDefinition definition, ITable table)
        {
            if (projectFeature.Project.Database.HasDefaultSchema(table))
            {
                definition.Namespaces.AddUnique(projectFeature.GetAspNetCoreProject().GetEntityLayerNamespace());
            }
            else
            {
                definition.Namespaces.AddUnique(projectFeature.GetAspNetCoreProject().GetEntityLayerNamespace(table.Schema));
            }

            var lines = new List <ILine>();

            var aspNetCoreProject   = projectFeature.GetAspNetCoreProject();
            var aspNetCoreSelection = aspNetCoreProject.GetSelection(table);
            var efCoreProject       = aspNetCoreProject.EntityFrameworkCoreProject;
            var efCoreSelection     = efCoreProject.GetSelection(table);

            if (aspNetCoreSelection.Settings.UseLogger)
            {
                lines.Add(new CodeLine("Logger?.LogDebug(\"'{{0}}' has been invoked\", nameof({0}));", aspNetCoreProject.GetControllerGetAllAsyncMethodName(table)));
                lines.Add(new CodeLine());
            }

            if (efCoreSelection.Settings.EntitiesWithDataContracts)
            {
                definition.Namespaces.AddUnique(projectFeature.GetAspNetCoreProject().GetDataLayerDataContractsNamespace());

                lines.Add(new CodeLine("var response = new PagedResponse<{0}>();", aspNetCoreProject.EntityFrameworkCoreProject.GetDataContractName(table)));
            }
            else
            {
                lines.Add(new CodeLine("var response = new PagedResponse<{0}>();", aspNetCoreProject.EntityFrameworkCoreProject.GetEntityName(table)));
            }

            lines.Add(new CodeLine());

            lines.Add(new CodeLine("try"));
            lines.Add(new CodeLine("{"));

            var parameters = new List <ParameterDefinition>
            {
                new ParameterDefinition("int?", "pageSize", "10"),
                new ParameterDefinition("int?", "pageNumber", "1")
            };

            var foreignKeys = new List <string>();

            foreach (var foreignKey in table.ForeignKeys)
            {
                var parentTable = projectFeature.Project.Database.FindTable(foreignKey.References);

                if (parentTable == null)
                {
                    continue;
                }

                if (parentTable.PrimaryKey?.Key.Count == 1)
                {
                    var column = parentTable.GetColumnsFromConstraint(parentTable.PrimaryKey).First();

                    parameters.Add(new ParameterDefinition(projectFeature.Project.Database.ResolveDatabaseType(column), aspNetCoreProject.CodeNamingConvention.GetParameterName(column.Name), "null"));

                    foreignKeys.Add(aspNetCoreProject.CodeNamingConvention.GetParameterName(column.Name));
                }
                else
                {
                    // todo: add logic for multiple columns in key
                }
            }

            lines.Add(new CommentLine(1, " Get query from repository"));

            if (foreignKeys.Count == 0)
            {
                lines.Add(new CodeLine(1, "var query = Repository.{0}();", aspNetCoreProject.EntityFrameworkCoreProject.GetGetAllRepositoryMethodName(table)));
            }
            else
            {
                lines.Add(new CodeLine(1, "var query = Repository.{0}({1});", aspNetCoreProject.EntityFrameworkCoreProject.GetGetAllRepositoryMethodName(table), string.Join(", ", foreignKeys)));
            }

            lines.Add(new CodeLine());

            if (aspNetCoreSelection.Settings.UseLogger)
            {
                lines.Add(new CommentLine(1, " Set paging's information"));
                lines.Add(new CodeLine(1, "response.PageSize = (int)pageSize;"));
                lines.Add(new CodeLine(1, "response.PageNumber = (int)pageNumber;"));
                lines.Add(new CodeLine(1, "response.ItemsCount = await query.CountAsync();"));
                lines.Add(new CodeLine());

                lines.Add(new CommentLine(1, " Retrieve items by page size and page number, set model for response"));
                lines.Add(new CodeLine(1, "response.Model = await query.Paging(response.PageSize, response.PageNumber).ToListAsync();"));
                lines.Add(new CodeLine());

                lines.Add(new CodeLine(1, "Logger?.LogInformation(\"Page {0} of {1}, Total of rows: {2}.\", response.PageNumber, response.PageCount, response.ItemsCount);"));
            }

            lines.Add(new CodeLine("}"));
            lines.Add(new CodeLine("catch (Exception ex)"));
            lines.Add(new CodeLine("{"));

            if (aspNetCoreSelection.Settings.UseLogger)
            {
                lines.Add(new CodeLine(1, "response.SetError(Logger, nameof({0}), ex);", aspNetCoreProject.GetControllerGetAllAsyncMethodName(table)));
            }
            else
            {
                lines.Add(new CodeLine(1, "response.DidError = true;"));
                lines.Add(new CodeLine(1, "response.ErrorMessage = ex.Message;"));
            }

            lines.Add(new CodeLine("}"));
            lines.Add(new CodeLine());
            lines.Add(new CodeLine("return response.ToHttpResponse();"));

            return(new MethodDefinition("Task<IActionResult>", aspNetCoreProject.GetControllerGetAllAsyncMethodName(table), parameters.ToArray())
            {
                AccessModifier = AccessModifier.Public,
                Attributes =
                {
                    new MetadataAttribute("HttpGet", string.Format("\"{0}\"", aspNetCoreProject.EntityFrameworkCoreProject.GetEntityName(table))),
                },
                IsAsync = true,
                Lines = lines
            });
        }
        public static CSharpClassDefinition GetRepositoryClassDefinition(this ProjectFeature <DapperProjectSettings> projectFeature)
        {
            var classDefinition = new CSharpClassDefinition();

            classDefinition.Namespaces.Add("System");
            classDefinition.Namespaces.Add("System.Collections.Generic");
            classDefinition.Namespaces.Add("System.Data");
            classDefinition.Namespaces.Add("System.Data.SqlClient");
            classDefinition.Namespaces.Add("System.Linq");
            classDefinition.Namespaces.Add("System.Text");
            classDefinition.Namespaces.Add("System.Threading.Tasks");
            classDefinition.Namespaces.Add("Dapper");
            classDefinition.Namespaces.Add("Microsoft.Extensions.Options");

            foreach (var table in projectFeature.Project.Database.Tables)
            {
                if (table.HasDefaultSchema())
                {
                    classDefinition.Namespaces.AddUnique(projectFeature.GetDapperProject().GetEntityLayerNamespace());
                }
                else
                {
                    classDefinition.Namespaces.AddUnique(projectFeature.GetDapperProject().GetEntityLayerNamespace(table.Schema));
                }

                classDefinition.Namespaces.AddUnique(projectFeature.GetDapperProject().GetDataLayerContractsNamespace());
            }

            classDefinition.Namespace = projectFeature.GetDapperProject().GetDataLayerRepositoriesNamespace();

            classDefinition.Name = projectFeature.GetClassRepositoryName();

            classDefinition.BaseClass = "Repository";

            classDefinition.Implements.Add(projectFeature.GetInterfaceRepositoryName());

            classDefinition.Constructors.Add(new ClassConstructorDefinition(new ParameterDefinition("IOptions<AppSettings>", "appSettings"))
            {
                Invocation = "base(appSettings)"
            });

            var dbos   = projectFeature.DbObjects.Select(dbo => dbo.FullName).ToList();
            var tables = projectFeature.Project.Database.Tables.Where(t => dbos.Contains(t.FullName)).ToList();
            var views  = projectFeature.Project.Database.Views.Where(v => dbos.Contains(v.FullName)).ToList();

            foreach (var table in tables)
            {
                classDefinition.Methods.Add(GetGetAllMethod(projectFeature, table));

                if (table.PrimaryKey != null)
                {
                    classDefinition.Methods.Add(GetGetMethod(projectFeature, table));
                }

                classDefinition.Methods.Add(GetAddMethod(projectFeature, table));

                if (table.PrimaryKey != null)
                {
                    classDefinition.Methods.Add(GetUpdateMethod(projectFeature, table));
                    classDefinition.Methods.Add(GetRemoveMethod(projectFeature, table));
                }

                foreach (var unique in table.Uniques)
                {
                    classDefinition.Methods.Add(GetByUniqueMethod(projectFeature, table, unique));
                }
            }

            foreach (var view in views)
            {
                classDefinition.Methods.Add(GetGetAllMethod(projectFeature, view));
            }

            return(classDefinition);
        }
        private static MethodDefinition GetDeleteMethod(ProjectFeature <AspNetCoreProjectSettings> projectFeature, ITable table)
        {
            var lines = new List <ILine>();

            var aspNetCoreProject = projectFeature.GetAspNetCoreProject();
            var selection         = aspNetCoreProject.GetSelection(table);

            if (selection.Settings.UseLogger)
            {
                lines.Add(new CodeLine("Logger?.LogDebug(\"'{{0}}' has been invoked\", nameof({0}));", aspNetCoreProject.GetControllerDeleteAsyncMethodName(table)));
                lines.Add(new CodeLine());
            }

            lines.Add(new CodeLine("var response = new Response();"));
            lines.Add(new CodeLine());

            lines.Add(new CodeLine("try"));
            lines.Add(new CodeLine("{"));

            if (table.PrimaryKey.Key.Count == 1)
            {
                lines.Add(new CommentLine(1, " Retrieve entity by id"));
                lines.Add(new CodeLine(1, "var entity = await Repository.{0}(new {1}(id));", aspNetCoreProject.EntityFrameworkCoreProject.GetGetRepositoryMethodName(table), aspNetCoreProject.EntityFrameworkCoreProject.GetEntityName(table)));
                lines.Add(new CodeLine());
            }
            else if (table.PrimaryKey.Key.Count > 1)
            {
                lines.Add(new CodeLine(1, "var key = id.Split('|');"));
                lines.Add(new CodeLine());

                var key = table.GetColumnsFromConstraint(table.PrimaryKey).ToList();

                for (var i = 0; i < key.Count; i++)
                {
                    var column = key[i];

                    var parameterName = aspNetCoreProject.CodeNamingConvention.GetParameterName(column.Name);

                    if (projectFeature.Project.Database.ColumnIsInt16(column))
                    {
                        lines.Add(new CodeLine(1, "var {0} = Convert.ToInt16(key[{1}]);", parameterName, (i + 1).ToString()));
                    }
                    else if (projectFeature.Project.Database.ColumnIsInt32(column))
                    {
                        lines.Add(new CodeLine(1, "var {0} = Convert.ToInt32(key[{1}]);", parameterName, (i + 1).ToString()));
                    }
                    else if (projectFeature.Project.Database.ColumnIsInt64(column))
                    {
                        lines.Add(new CodeLine(1, "var {0} = Convert.ToInt64(key[{1}]);", parameterName, (i + 1).ToString()));
                    }
                    else
                    {
                        lines.Add(new CodeLine(1, "var {0} = key[{1}];", parameterName, (i + 1).ToString()));
                    }
                }

                var exp = string.Join(", ", key.Select(item => string.Format("{0}", aspNetCoreProject.CodeNamingConvention.GetParameterName(item.Name))));

                lines.Add(new CommentLine(1, " Retrieve entity"));
                lines.Add(new CodeLine(1, "var entity = await Repository.{0}(new {1}({2}));", aspNetCoreProject.EntityFrameworkCoreProject.GetGetRepositoryMethodName(table), aspNetCoreProject.EntityFrameworkCoreProject.GetEntityName(table), exp));
                lines.Add(new CodeLine());
            }

            lines.Add(new CodeLine(1, "if (entity != null)"));
            lines.Add(new CodeLine(1, "{"));

            lines.Add(new CommentLine(2, " Remove entity from database"));
            lines.Add(new CodeLine(2, "Repository.Remove(entity);"));

            lines.Add(new CodeLine());
            lines.Add(new CodeLine(2, "await Repository.CommitChangesAsync();"));

            if (selection.Settings.UseLogger)
            {
                lines.Add(new CodeLine());
                lines.Add(new CodeLine(2, "Logger?.LogInformation(\"The entity was deleted successfully\");"));
            }

            lines.Add(new CodeLine(1, "}"));

            lines.Add(new CodeLine("}"));
            lines.Add(new CodeLine("catch (Exception ex)"));
            lines.Add(new CodeLine("{"));

            if (selection.Settings.UseLogger)
            {
                lines.Add(new CodeLine(1, "response.SetError(Logger, nameof({0}), ex);", aspNetCoreProject.GetControllerDeleteAsyncMethodName(table)));
            }
            else
            {
                lines.Add(new CodeLine(1, "response.DidError = true;"));
                lines.Add(new CodeLine(1, "response.ErrorMessage = ex.Message;"));
            }

            lines.Add(new CodeLine("}"));
            lines.Add(new CodeLine());

            lines.Add(new CodeLine("return response.ToHttpResponse();"));

            var parameters = new List <ParameterDefinition>();

            if (table.PrimaryKey.Key.Count == 1)
            {
                var column = table.GetColumnsFromConstraint(table.PrimaryKey).First();

                parameters.Add(new ParameterDefinition(projectFeature.Project.Database.ResolveDatabaseType(column), "id"));
            }
            else if (table.PrimaryKey.Key.Count > 1)
            {
                parameters.Add(new ParameterDefinition("string", "id"));
            }

            return(new MethodDefinition("Task<IActionResult>", aspNetCoreProject.GetControllerDeleteAsyncMethodName(table), parameters.ToArray())
            {
                Attributes =
                {
                    new MetadataAttribute("HttpDelete", string.Format("\"{0}/{{id}}\"", aspNetCoreProject.EntityFrameworkCoreProject.GetEntityName(table))),
                },
                AccessModifier = AccessModifier.Public,
                IsAsync = true,
                Lines = lines
            });
        }
        private static MethodDefinition GetPostMethod(ProjectFeature <AspNetCoreProjectSettings> projectFeature, ITable table)
        {
            var lines = new List <ILine>();

            var aspNetCoreProject = projectFeature.GetAspNetCoreProject();
            var selection         = aspNetCoreProject.GetSelection(table);

            if (selection.Settings.UseLogger)
            {
                lines.Add(new CodeLine("Logger?.LogDebug(\"'{{0}}' has been invoked\", nameof({0}));", aspNetCoreProject.GetControllerPostAsyncMethodName(table)));
                lines.Add(new CodeLine());
            }

            lines.Add(new CommentLine(" Validate request model"));
            lines.Add(new CodeLine("if (!ModelState.IsValid)"));
            lines.Add(new CodeLine(1, "return BadRequest(request);"));
            lines.Add(new CodeLine());

            lines.Add(new CodeLine("var response = new SingleResponse<{0}>();", aspNetCoreProject.GetRequestName(table)));
            lines.Add(new CodeLine());

            lines.Add(new CodeLine("try"));
            lines.Add(new CodeLine("{"));

            lines.Add(new CodeLine(1, "var entity = request.ToEntity();", aspNetCoreProject.EntityFrameworkCoreProject.GetAddRepositoryMethodName(table)));
            lines.Add(new CodeLine());

            foreach (var unique in table.Uniques)
            {
                lines.Add(new CommentLine(1, " Check if entity exists"));
                lines.Add(new CodeLine(1, "if ((await Repository.{0}(entity)) != null)", aspNetCoreProject.EntityFrameworkCoreProject.GetGetByUniqueRepositoryMethodName(table, unique)));
                lines.Add(new CodeLine(1, "{"));
                lines.Add(new CodeLine(2, "return BadRequest();"));
                lines.Add(new CodeLine(1, "}"));
                lines.Add(new CodeLine());
            }

            lines.Add(new CommentLine(1, " Add entity to database"));
            lines.Add(new CodeLine(1, "Repository.Add(entity);"));
            lines.Add(new CodeLine());
            lines.Add(new CodeLine(1, "await Repository.CommitChangesAsync();"));
            lines.Add(new CodeLine());

            lines.Add(new CodeLine(1, "response.Model = entity.ToRequest();"));

            if (selection.Settings.UseLogger)
            {
                lines.Add(new CodeLine());
                lines.Add(new CodeLine(1, "Logger?.LogInformation(\"The entity was created successfully\");"));
            }

            lines.Add(new CodeLine("}"));
            lines.Add(new CodeLine("catch (Exception ex)"));
            lines.Add(new CodeLine("{"));

            if (selection.Settings.UseLogger)
            {
                lines.Add(new CodeLine(1, "response.SetError(Logger, nameof({0}), ex);", aspNetCoreProject.GetControllerPostAsyncMethodName(table)));
            }
            else
            {
                lines.Add(new CodeLine(1, "response.DidError = true;"));
                lines.Add(new CodeLine(1, "response.ErrorMessage = ex.Message;"));
            }

            lines.Add(new CodeLine("}"));
            lines.Add(new CodeLine());

            lines.Add(new CodeLine("return response.ToHttpResponse();"));

            return(new MethodDefinition("Task<IActionResult>", aspNetCoreProject.GetControllerPostAsyncMethodName(table), new ParameterDefinition(aspNetCoreProject.GetRequestName(table), "request", new MetadataAttribute("FromBody")))
            {
                Attributes =
                {
                    new MetadataAttribute("HttpPost", string.Format("\"{0}\"", aspNetCoreProject.EntityFrameworkCoreProject.GetEntityName(table))),
                },
                AccessModifier = AccessModifier.Public,
                IsAsync = true,
                Lines = lines
            });
        }
        public static ControllerClassDefinition GetControllerClassDefinition(this ProjectFeature <AspNetCoreProjectSettings> projectFeature)
        {
            var aspNetCoreProject = projectFeature.GetAspNetCoreProject();

            var definition = new ControllerClassDefinition
            {
                Namespaces =
                {
                    "System",
                    "System.Linq",
                    "System.Threading.Tasks",
                    "Microsoft.AspNetCore.Mvc",
                    "Microsoft.EntityFrameworkCore",
                    "Microsoft.Extensions.Logging",
                    aspNetCoreProject.GetDataLayerContractsNamespace(),
                    aspNetCoreProject.GetDataLayerRepositoriesNamespace(),
                    aspNetCoreProject.GetResponsesNamespace(),
                    aspNetCoreProject.GetRequestsNamespace()
                },
                Namespace      = string.Format("{0}.{1}", aspNetCoreProject.Name, "Controllers"),
                AccessModifier = AccessModifier.Public,
                Name           = projectFeature.GetControllerName(),
                Attributes     = new List <MetadataAttribute>
                {
                    new MetadataAttribute("Route", string.IsNullOrEmpty(aspNetCoreProject.Version) ? "\"api/[controller]\"" : string.Format("\"api/{0}/[controller]\"", aspNetCoreProject.Version)),
                    new MetadataAttribute("ApiController")
                },
                BaseClass = "ControllerBase",
                Fields    =
                {
                    new FieldDefinition(AccessModifier.Protected, projectFeature.GetInterfaceRepositoryName(), "Repository")
                    {
                        IsReadOnly = true
                    }
                }
            };

            var settings = aspNetCoreProject.GlobalSelection().Settings;

            if (settings.UseLogger)
            {
                definition.Fields.Add(new FieldDefinition(AccessModifier.Protected, "ILogger", "Logger"));
            }

            definition.Constructors.Add(GetConstructor(projectFeature));

            var dbos   = projectFeature.DbObjects.Select(dbo => dbo.FullName).ToList();
            var tables = projectFeature.Project.Database.Tables.Where(t => dbos.Contains(t.FullName)).ToList();

            foreach (var table in tables)
            {
                if (table.Columns.Count == table.PrimaryKey?.Key.Count)
                {
                    continue;
                }

                definition.Methods.Add(GetGetAllMethod(projectFeature, definition, table));

                if (table.PrimaryKey != null)
                {
                    definition.Methods.Add(GetGetMethod(projectFeature, table));
                }

                definition.Methods.Add(GetPostMethod(projectFeature, table));

                if (table.PrimaryKey != null)
                {
                    definition.Methods.Add(GetPutMethod(projectFeature, table));

                    definition.Methods.Add(GetDeleteMethod(projectFeature, table));
                }
            }

            // todo: Add views in controller

            definition.SimplifyDataTypes();

            return(definition);
        }