private CSharpRepoGenerator.RepositoryFunction GenerateListByForeignKey(RepositoryMemberInfo repositoryMembmerInfo) { string returnType = GetClassName(repositoryMembmerInfo); var mainKey = repositoryMembmerInfo.Info.QueryKey; string mainKeyType = GetMemberType(mainKey); string methodSuffix = mainKey.HasReference && (!Config.Entities.StrongTypes || !CanBeStronger(mainKey)) ? mainKey.Name : ""; string mainKeyFieldLower = StringExt.ToCamelCase(mainKey.Name); var signature = $"Task<List<{returnType}>> GetBy{methodSuffix}({mainKeyType} {mainKeyFieldLower})"; var template = $@" public async {signature} {{ using (var db = GetDb()) {{ var payload = new {{ {mainKey.Name} = {StrongTypeCastingType(mainKey)}{mainKeyFieldLower} }}; var result = await db.QuerySprocAsync<{returnType}>(""{repositoryMembmerInfo.Info.Name}"", payload).ConfigureAwait(continueOnCapturedContext: false); return result.ToList(); }} }}"; return(new CSharpRepoGenerator.RepositoryFunction { Body = template, Signature = signature }); }
private CSharpRepoGenerator.RepositoryFunction GenerateUpdate(RepositoryMemberInfo repositoryMembmerInfo) { var className = CSharpCodeClassGenerator.GetClassName(repositoryMembmerInfo.Info.BaseAtom); string updateFields = GetUpdateFields(repositoryMembmerInfo, StringExt.ToCamelCase(className)) .IndentAllLines(7, true); var signature = $"Task Update({className} {StringExt.ToCamelCase(className)})"; var template = $@" public async {signature} {{ using (var db = GetDb()) {{ var payload = new {{ {updateFields} }}; await db.ExecSprocAsync(""{repositoryMembmerInfo.Info.Name}"", payload).ConfigureAwait(continueOnCapturedContext: false); }} }}"; return(new CSharpRepoGenerator.RepositoryFunction { Body = template, Signature = signature }); }
private CSharpRepoGenerator.RepositoryFunction GenerateSoftDelete(RepositoryMemberInfo repositoryMembmerInfo) { var mainKey = repositoryMembmerInfo.Info.QueryKey; string mainKeyName = mainKey.Name; string mainKeyType = GetMemberType(mainKey); string mainKeyFieldLower = StringExt.ToCamelCase(mainKey.Name); string strongTypeCasting = StrongTypeCastingType(mainKey); var signature = $"Task SoftDelete({mainKeyType} {mainKeyFieldLower})"; var template = $@" public async {signature} {{ using (var db = GetDb()) {{ var payload = new {{ {mainKeyName} = {strongTypeCasting}{mainKeyFieldLower} }}; await db.ExecSprocAsync(""{repositoryMembmerInfo.Info.Name}"", payload).ConfigureAwait(continueOnCapturedContext: false); }} }}"; return(new CSharpRepoGenerator.RepositoryFunction { Body = template, Signature = signature }); }
private CSharpRepoGenerator.RepositoryFunction GenerateUpsert(RepositoryMemberInfo repositoryMembmerInfo) { var className = GetClassName(repositoryMembmerInfo); string typeName = StringExt.ToCamelCase(className); var mainKey = FindMainKey(repositoryMembmerInfo.Info.BaseAtom); string keyType = GetMemberType(mainKey); string updateFields = GetUpdateFields(repositoryMembmerInfo, StringExt.ToCamelCase(className)) .IndentAllLines(7, true); var signature = $"Task<{keyType}> Upsert({className} {typeName})"; var template = $@" public async {signature} {{ using (var db = GetDb()) {{ var payload = new {{ {updateFields} }}; return (await db.QuerySprocAsync<{keyType}>(""{repositoryMembmerInfo.Info.Name}"", payload).ConfigureAwait(continueOnCapturedContext: false)).FirstOrDefault(); }} }}"; return(new CSharpRepoGenerator.RepositoryFunction { Body = template, Signature = signature }); }
private CSharpRepoGenerator.RepositoryFunction GenerateBatchList(RepositoryMemberInfo repositoryMembmerInfo) { string returnType = GetClassName(repositoryMembmerInfo); var mainKey = repositoryMembmerInfo.Info.QueryKey; string mainKeyType = GetMemberType(mainKey); string mainKeyRealType = new CSharpDefaultTypeFinder(mainKey.Optional).Visit(mainKey.MemberType); string casting = Config.Entities.StrongTypes ? $"Select(id => ({mainKeyRealType})id).ToList()." : string.Empty; var signature = $"Task<List<{returnType}>> GetMany(IEnumerable<{mainKeyType}> ids)"; var template = $@" public async {signature} {{ using (var db = GetDb()) {{ var payload = new {{ LookupKeys = ids.{casting}ToDataTable() }}; var result = await db.QuerySprocAsync<{returnType}>(""{repositoryMembmerInfo.Info.Name}"", payload).ConfigureAwait(continueOnCapturedContext: false); return result.ToList(); }} }}"; return(new CSharpRepoGenerator.RepositoryFunction { Body = template, Signature = signature }); }
private CSharpRepoGenerator.RepositoryFunction GenerateMember(RepositoryMemberInfo arg) { switch (arg.Info.QueryType) { case QueryType.Insert: return(GenerateInsert(arg)); case QueryType.Upsert: return(GenerateUpsert(arg)); case QueryType.Update: return(GenerateUpdate(arg)); case QueryType.Delete: return(GenerateSoftDelete(arg)); case QueryType.GetOne: return(GenerateList(arg)); case QueryType.GetBy: return(GenerateListByForeignKey(arg)); case QueryType.GetAll: return(GenerateGetAll(arg)); case QueryType.BatchList: return(GenerateBatchList(arg)); default: throw new ArgumentOutOfRangeException(); } }
private CSharpRepoGenerator.RepositoryFunction GenerateList(RepositoryMemberInfo repositoryMembmerInfo) { if (repositoryMembmerInfo.Info.QueryKey?.HasReference ?? false) { return(GenerateListByForeignKey(repositoryMembmerInfo)); } return(GenerateListByPrimaryKey(repositoryMembmerInfo)); }
private string CreateAccessor(RepositoryMemberInfo arg) { if (arg.Info.QueryType != QueryType.View) { return GenericAccessor(arg); } return ViewAccessor(arg); }
private string CreateAccessor(RepositoryMemberInfo arg) { if (arg.Info.QueryType != QueryType.View) { return(GenericAccessor(arg)); } return(ViewAccessor(arg)); }
private string ViewAccessor(RepositoryMemberInfo repositoryMemberInfo) { string returnType = GetClassName(repositoryMemberInfo); var template = $@" public IReadOnlyTable<{returnType}> {repositoryMemberInfo.Info.BaseAtom.Name} {{ get {{ return CreateTable<{returnType}>(tableName: ""{repositoryMemberInfo.Info.Name}""); }} }}"; return(template); }
private CSharpRepoGenerator.RepositoryFunction GenerateInsert(RepositoryMemberInfo repositoryMemberInfo) { var className = GetClassName(repositoryMemberInfo); string typeName = StringExt.ToCamelCase(className); var mainKey = FindMainKey(repositoryMemberInfo.Info.BaseAtom); if (mainKey == null) { throw new Exception(String.Format("{0} has no main key", repositoryMemberInfo.BaseAtomTypeName)); } string keyType = GetMemberType(mainKey); string updateFields = GetUpdateFields(repositoryMemberInfo, StringExt.ToCamelCase(className)) .IndentAllLines(7, true); string signature; string finalStatement; if (repositoryMemberInfo.Info.BaseAtom.BasedOn.AdditionalInfo.SelectAfterInsert.GetValueOrDefault(true)) { signature = $"Task<{keyType}> Insert({className} {typeName})"; finalStatement = $@"return (await db.QuerySprocAsync<{keyType}>(""{repositoryMemberInfo.Info.Name}"", payload).ConfigureAwait(continueOnCapturedContext: false)).FirstOrDefault();"; } else { signature = $"Task Insert({className} {typeName})"; finalStatement = $@"await db.ExecSprocAsync(""{repositoryMemberInfo.Info.Name}"", payload).ConfigureAwait(continueOnCapturedContext: false);"; } var template = $@" public async {signature} {{ using (var db = GetDb()) {{ var payload = new {{ {updateFields} }}; {finalStatement} }} }}"; return(new CSharpRepoGenerator.RepositoryFunction { Body = template, Signature = signature }); }
private string GenericAccessor(RepositoryMemberInfo repositoryMemberInfo) { string returnType = GetClassName(repositoryMemberInfo); var key = FindMainKey(repositoryMemberInfo.Info.BaseAtom); string keyType = GetMemberType(key); var template = $@" public Table<{returnType}, {keyType}> {repositoryMemberInfo.Info.BaseAtom.Name} {{ get {{ return CreateTable<{returnType}, {keyType}>(i => i.{key.Name}); }} }}"; return(template); }
private string GetUpdateFields(RepositoryMemberInfo repositoryMembmerInfo, string className) { var queryParams = repositoryMembmerInfo.Info.InputParams.Select( memberInfo => { var parameterName = memberInfo.Name; if (memberInfo.HasReference && memberInfo.Reference.IsReferenceToHiddenPrimaryKey) { parameterName = memberInfo.Reference.TargetAtomAlternateKey.Name; } string memberName = new CSharpMemberNameFinder(memberInfo).MemberName(); return($"{parameterName} = {StrongTypeCastingType(memberInfo)}({className}.{memberName})"); }); return(string.Join("," + Environment.NewLine, queryParams) .Trim()); }
private CSharpRepoGenerator.RepositoryFunction GenerateGetAll(RepositoryMemberInfo repositoryMembmerInfo) { string verb = "GetAll"; string returnType = GetClassName(repositoryMembmerInfo); var signature = $"Task<List<{returnType}>> {verb}()"; var template = $@" public async {signature} {{ using (var db = GetDb()) {{ var result = await db.QuerySprocAsync<{returnType}>(""{repositoryMembmerInfo.Info.Name}"").ConfigureAwait(continueOnCapturedContext: false); return result.ToList(); }} }}"; return(new CSharpRepoGenerator.RepositoryFunction { Body = template, Signature = signature }); }
protected string GetClassName(RepositoryMemberInfo repositoryMembmerInfo) { return(CSharpCodeClassGenerator.GetClassName(repositoryMembmerInfo.Info.BaseAtom)); }
private CSharpRepoGenerator.RepositoryFunction GenerateListByPrimaryKey(RepositoryMemberInfo repositoryMemberInfo) { var mainKey = repositoryMemberInfo.Info.QueryKey; var MethodSuffix = mainKey.HasReference && (!Config.Entities.StrongTypes || !CanBeStronger(mainKey)) ? "By" + mainKey.Name : ""; string returnType = GetClassName(repositoryMemberInfo); string mainKeyName = mainKey.Name; string mainKeyType = GetMemberType(mainKey); string mainKeyFieldLower = StringExt.ToCamelCase(mainKey.Name); string sprocName = repositoryMemberInfo.Info.Name; string strongTypeCasting = StrongTypeCastingType(mainKey); var signature = $"Task<{returnType}> GetOne{MethodSuffix}({mainKeyType} {mainKeyFieldLower})"; var template = $@" public async {signature} {{ using (var db = GetDb()) {{ var payload = new {{ {mainKeyName} = {strongTypeCasting}{mainKeyFieldLower} }}; var result = await db.QuerySprocAsync<{returnType}>(""{sprocName}"", payload).ConfigureAwait(continueOnCapturedContext: false); return result.FirstOrDefault(); }} }}"; return new CSharpRepoGenerator.RepositoryFunction { Body = template, Signature = signature }; }
private CSharpRepoGenerator.RepositoryFunction GenerateMember(RepositoryMemberInfo arg) { switch (arg.Info.QueryType) { case QueryType.Insert: return GenerateInsert(arg); case QueryType.Upsert: return GenerateUpsert(arg); case QueryType.Update: return GenerateUpdate(arg); case QueryType.Delete: return GenerateSoftDelete(arg); case QueryType.GetOne: return GenerateList(arg); case QueryType.GetBy: return GenerateListByForeignKey(arg); case QueryType.GetAll: return GenerateGetAll(arg); case QueryType.BatchList: return GenerateBatchList(arg); default: throw new ArgumentOutOfRangeException(); } }
private CSharpRepoGenerator.RepositoryFunction GenerateSoftDelete(RepositoryMemberInfo repositoryMembmerInfo) { var mainKey = repositoryMembmerInfo.Info.QueryKey; string mainKeyName = mainKey.Name; string mainKeyType = GetMemberType(mainKey); string mainKeyFieldLower = StringExt.ToCamelCase(mainKey.Name); string strongTypeCasting = StrongTypeCastingType(mainKey); var signature = $"Task SoftDelete({mainKeyType} {mainKeyFieldLower})"; var template = $@" public async {signature} {{ using (var db = GetDb()) {{ var payload = new {{ {mainKeyName} = {strongTypeCasting}{mainKeyFieldLower} }}; await db.ExecSprocAsync(""{repositoryMembmerInfo.Info.Name}"", payload).ConfigureAwait(continueOnCapturedContext: false); }} }}"; return new CSharpRepoGenerator.RepositoryFunction { Body = template, Signature = signature }; }
private CSharpRepoGenerator.RepositoryFunction GenerateList(RepositoryMemberInfo repositoryMembmerInfo) { if (repositoryMembmerInfo.Info.QueryKey?.HasReference ?? false) { return GenerateListByForeignKey(repositoryMembmerInfo); } return GenerateListByPrimaryKey(repositoryMembmerInfo); }
private string GenericAccessor(RepositoryMemberInfo repositoryMemberInfo) { string returnType = GetClassName(repositoryMemberInfo); var key = FindMainKey(repositoryMemberInfo.Info.BaseAtom); string keyType = GetMemberType(key); var template = $@" public Table<{returnType}, {keyType}> {repositoryMemberInfo.Info.BaseAtom.Name} {{ get {{ return CreateTable<{returnType}, {keyType}>(i => i.{key.Name}); }} }}"; return template; }
private CSharpRepoGenerator.RepositoryFunction GenerateUpdate(RepositoryMemberInfo repositoryMembmerInfo) { var className = CSharpCodeClassGenerator.GetClassName(repositoryMembmerInfo.Info.BaseAtom); string updateFields = GetUpdateFields(repositoryMembmerInfo, StringExt.ToCamelCase(className)) .IndentAllLines(7, true); var signature = $"Task Update({className} {StringExt.ToCamelCase(className)})"; var template = $@" public async {signature} {{ using (var db = GetDb()) {{ var payload = new {{ {updateFields} }}; await db.ExecSprocAsync(""{repositoryMembmerInfo.Info.Name}"", payload).ConfigureAwait(continueOnCapturedContext: false); }} }}"; return new CSharpRepoGenerator.RepositoryFunction { Body = template, Signature = signature }; }
private CSharpRepoGenerator.RepositoryFunction GenerateBatchList(RepositoryMemberInfo repositoryMembmerInfo) { string returnType = GetClassName(repositoryMembmerInfo); var mainKey = repositoryMembmerInfo.Info.QueryKey; string mainKeyType = GetMemberType(mainKey); string mainKeyRealType = new CSharpDefaultTypeFinder(mainKey.Optional).Visit(mainKey.MemberType); string casting = Config.Entities.StrongTypes ? $"Select(id => ({mainKeyRealType})id).ToList()." : string.Empty; var signature = $"Task<List<{returnType}>> GetMany(IEnumerable<{mainKeyType}> ids)"; var template = $@" public async {signature} {{ using (var db = GetDb()) {{ var payload = new {{ LookupKeys = ids.{casting}ToDataTable() }}; var result = await db.QuerySprocAsync<{returnType}>(""{repositoryMembmerInfo.Info.Name}"", payload).ConfigureAwait(continueOnCapturedContext: false); return result.ToList(); }} }}"; return new CSharpRepoGenerator.RepositoryFunction { Body = template, Signature = signature }; }
private string GetUpdateFields(RepositoryMemberInfo repositoryMembmerInfo, string className) { var queryParams = repositoryMembmerInfo.Info.InputParams.Select( memberInfo => { var parameterName = memberInfo.Name; if (memberInfo.HasReference && memberInfo.Reference.IsReferenceToHiddenPrimaryKey) { parameterName = memberInfo.Reference.TargetAtomAlternateKey.Name; } string memberName = new CSharpMemberNameFinder(memberInfo).MemberName(); return $"{parameterName} = {StrongTypeCastingType(memberInfo)}({className}.{memberName})"; }); return string.Join("," + Environment.NewLine, queryParams) .Trim(); }
private CSharpRepoGenerator.RepositoryFunction GenerateUpsert(RepositoryMemberInfo repositoryMembmerInfo) { var className = GetClassName(repositoryMembmerInfo); string typeName = StringExt.ToCamelCase(className); var mainKey = FindMainKey(repositoryMembmerInfo.Info.BaseAtom); string keyType = GetMemberType(mainKey); string updateFields = GetUpdateFields(repositoryMembmerInfo, StringExt.ToCamelCase(className)) .IndentAllLines(7, true); var signature = $"Task<{keyType}> Upsert({className} {typeName})"; var template = $@" public async {signature} {{ using (var db = GetDb()) {{ var payload = new {{ {updateFields} }}; return (await db.QuerySprocAsync<{keyType}>(""{repositoryMembmerInfo.Info.Name}"", payload).ConfigureAwait(continueOnCapturedContext: false)).FirstOrDefault(); }} }}"; return new CSharpRepoGenerator.RepositoryFunction { Body = template, Signature = signature }; }
private string GenerateStrongTypeInitializers(string groupName, RepositoryMemberInfo sample) { if (!Config.Entities.StrongTypes) { return(string.Empty); } return($@" public partial class {groupName} {{ public Database() {{ InitTypeMappings(); }} public static void InitTypeMappings() {{ // get assembly where data records live var strongTypes = Assembly.GetAssembly(typeof({GetClassName(sample)})) .FindStrongTypes(); foreach (var strongType in strongTypes) {{ SqlMapper.AddTypeHandler(strongType, new StrongTypeMapper()); }} }} }} internal class StrongTypeMapper : SqlMapper.ITypeHandler {{ public void SetValue(IDbDataParameter parameter, object value) {{ parameter.DbType = new DbTypeStrongVisitor().Visit(value as IAcceptStrongTypeVisitor); parameter.Value = new UnderlyingStrongTypeVisitor().Visit(value as IAcceptStrongTypeVisitor); }} public object Parse(Type destinationType, object value) {{ var targetType = Nullable.GetUnderlyingType(destinationType) ?? destinationType; return Activator.CreateInstance( targetType, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static, binder: null, args: new[] {{ value }}, culture: null); }} }} internal class DbTypeStrongVisitor : IStrongTypeVistor<DbType> {{ public DbType Visit(ITypedGuid guid) {{ return DbType.Guid; }} public DbType Visit(ITypedInt data) {{ return DbType.Int32; }} public DbType Visit(ITypedLong data) {{ return DbType.Int64; }} public DbType Visit(ITypedFloat data) {{ return DbType.Double; }} public DbType Visit(ITypedDouble data) {{ return DbType.Decimal; }} public DbType Visit(ITypedShort data) {{ return DbType.Int16; }} public DbType Visit(ITypedByte data) {{ return DbType.Byte; }} public DbType Visit(ITypedDateTime data) {{ return DbType.DateTime; }} public DbType Visit(ITypedString data) {{ return DbType.String; }} public DbType Visit(IAcceptStrongTypeVisitor visitor) {{ return visitor.Accept(this); }} }}"); }
private CSharpRepoGenerator.RepositoryFunction GenerateGetAll(RepositoryMemberInfo repositoryMembmerInfo) { string verb = "GetAll"; string returnType = GetClassName(repositoryMembmerInfo); var signature = $"Task<List<{returnType}>> {verb}()"; var template = $@" public async {signature} {{ using (var db = GetDb()) {{ var result = await db.QuerySprocAsync<{returnType}>(""{repositoryMembmerInfo.Info.Name}"").ConfigureAwait(continueOnCapturedContext: false); return result.ToList(); }} }}"; return new CSharpRepoGenerator.RepositoryFunction { Body = template, Signature = signature }; }
private string ViewAccessor(RepositoryMemberInfo repositoryMemberInfo) { string returnType = GetClassName(repositoryMemberInfo); var template = $@" public IReadOnlyTable<{returnType}> {repositoryMemberInfo.Info.BaseAtom.Name} {{ get {{ return CreateTable<{returnType}>(tableName: ""{repositoryMemberInfo.Info.Name}""); }} }}"; return template; }
private CSharpRepoGenerator.RepositoryFunction GenerateInsert(RepositoryMemberInfo repositoryMemberInfo) { var className = GetClassName(repositoryMemberInfo); string typeName = StringExt.ToCamelCase(className); var mainKey = FindMainKey(repositoryMemberInfo.Info.BaseAtom); if (mainKey == null) { throw new Exception(String.Format("{0} has no main key", repositoryMemberInfo.BaseAtomTypeName)); } string keyType = GetMemberType(mainKey); string updateFields = GetUpdateFields(repositoryMemberInfo, StringExt.ToCamelCase(className)) .IndentAllLines(7, true); string signature; string finalStatement; if (repositoryMemberInfo.Info.BaseAtom.BasedOn.AdditionalInfo.SelectAfterInsert.GetValueOrDefault(true)) { signature = $"Task<{keyType}> Insert({className} {typeName})"; finalStatement = $@"return (await db.QuerySprocAsync<{keyType}>(""{repositoryMemberInfo.Info.Name}"", payload).ConfigureAwait(continueOnCapturedContext: false)).FirstOrDefault();"; } else { signature = $"Task Insert({className} {typeName})"; finalStatement = $@"await db.ExecSprocAsync(""{repositoryMemberInfo.Info.Name}"", payload).ConfigureAwait(continueOnCapturedContext: false);"; } var template = $@" public async {signature} {{ using (var db = GetDb()) {{ var payload = new {{ {updateFields} }}; {finalStatement} }} }}"; return new CSharpRepoGenerator.RepositoryFunction { Body = template, Signature = signature }; }
private string GenerateStrongTypeInitializers(string groupName, RepositoryMemberInfo sample) { if (!Config.Entities.StrongTypes) { return string.Empty; } return $@" public partial class {groupName} {{ public Database() {{ InitTypeMappings(); }} public static void InitTypeMappings() {{ // get assembly where data records live var strongTypes = Assembly.GetAssembly(typeof({GetClassName(sample)})) .FindStrongTypes(); foreach (var strongType in strongTypes) {{ SqlMapper.AddTypeHandler(strongType, new StrongTypeMapper()); }} }} }} internal class StrongTypeMapper : SqlMapper.ITypeHandler {{ public void SetValue(IDbDataParameter parameter, object value) {{ parameter.DbType = new DbTypeStrongVisitor().Visit(value as IAcceptStrongTypeVisitor); parameter.Value = new UnderlyingStrongTypeVisitor().Visit(value as IAcceptStrongTypeVisitor); }} public object Parse(Type destinationType, object value) {{ var targetType = Nullable.GetUnderlyingType(destinationType) ?? destinationType; return Activator.CreateInstance( targetType, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static, binder: null, args: new[] {{ value }}, culture: null); }} }} internal class DbTypeStrongVisitor : IStrongTypeVistor<DbType> {{ public DbType Visit(ITypedGuid guid) {{ return DbType.Guid; }} public DbType Visit(ITypedInt data) {{ return DbType.Int32; }} public DbType Visit(ITypedLong data) {{ return DbType.Int64; }} public DbType Visit(ITypedFloat data) {{ return DbType.Double; }} public DbType Visit(ITypedDouble data) {{ return DbType.Decimal; }} public DbType Visit(ITypedShort data) {{ return DbType.Int16; }} public DbType Visit(ITypedByte data) {{ return DbType.Byte; }} public DbType Visit(ITypedDateTime data) {{ return DbType.DateTime; }} public DbType Visit(ITypedString data) {{ return DbType.String; }} public DbType Visit(IAcceptStrongTypeVisitor visitor) {{ return visitor.Accept(this); }} }}"; }
protected string GetClassName(RepositoryMemberInfo repositoryMembmerInfo) { return CSharpCodeClassGenerator.GetClassName(repositoryMembmerInfo.Info.BaseAtom); }