Update API

This commit is contained in:
Chris Chen 2022-09-30 09:40:42 -07:00
parent 184db15773
commit b33c0d8286
55 changed files with 3877 additions and 360 deletions

View File

@ -4,7 +4,9 @@ using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Church.Net.Entity; using Church.Net.Entity;
using Church.Net.Entity.Messenger;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
namespace Church.Net.DAL.EF namespace Church.Net.DAL.EF
{ {
@ -17,7 +19,7 @@ namespace Church.Net.DAL.EF
// public ChurchNetContext(string connString):base(connString) // public ChurchNetContext(string connString):base(connString)
// { // {
// } // }
// //public DbSet<PastoralDomain> PastoralDomains { get; set; } // //public DbSet<PastoralDomain> PastoralDomains { get; set; }
// //public DbSet<FamilyMember> FamilyMembers { get; set; } // //public DbSet<FamilyMember> FamilyMembers { get; set; }
@ -36,7 +38,10 @@ namespace Church.Net.DAL.EF
public class ChurchNetContext : DbContext public class ChurchNetContext : DbContext
{ {
private static bool _created = true; private static bool _created = true;
public ChurchNetContext(DbContextOptions<ChurchNetContext> options) :base(options) private readonly string connectionString;
public ChurchNetContext(DbContextOptions<ChurchNetContext> options) : base(options)
{ {
} }
@ -53,23 +58,23 @@ namespace Church.Net.DAL.EF
// Database.EnsureCreated(); // Database.EnsureCreated();
// } // }
//} //}
//public ChurchNetContext(string connectionString) public ChurchNetContext(string connectionString)
//{ {
// var folder = Environment.SpecialFolder.LocalApplicationData; this.connectionString = connectionString;
// var path = Environment.GetFolderPath(folder);
// DbPath = System.IO.Path.Join(path, "ChurchNet.db"); }
// DbPath = @"C:\WebSites\ChurchNetAPI\App_Data\ChurchNet.db"; protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
// if (!_created) {
// { if (!string.IsNullOrWhiteSpace(connectionString))
// _created = true; {
// Database.EnsureDeleted(); optionsBuilder.UseNpgsql(connectionString);
// Database.EnsureCreated(); }
// }
//} }
//public DbSet<PastoralDomain> PastoralDomains { get; set; } //public DbSet<PastoralDomain> PastoralDomains { get; set; }
//public DbSet<FamilyMember> FamilyMembers { get; set; } //public DbSet<FamilyMember> FamilyMembers { get; set; }
//public DbSet<Career> Careers { get; set; } //public DbSet<Career> Careers { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder) protected override void OnModelCreating(ModelBuilder modelBuilder)
{ {
//modelBuilder.Conventions.Remove<PluralizingTableNameConvention>(); //modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
@ -78,7 +83,7 @@ namespace Church.Net.DAL.EF
modelBuilder.Entity<CellGroupRoutineEventPrayer>() modelBuilder.Entity<CellGroupRoutineEventPrayer>()
.HasKey(tt => new { tt.EventId, tt.MemberId }); .HasKey(tt => new { tt.EventId, tt.MemberId });
modelBuilder.Entity<FamilyMemberOAuth>() modelBuilder.Entity<FamilyMemberOAuth>()
.HasKey(tt => new { tt.FamilyMemberId, tt.OAuthType }); .HasKey(tt => new { tt.FamilyMemberId, tt.OAuthType });
@ -91,9 +96,9 @@ namespace Church.Net.DAL.EF
.HasKey(tt => new { tt.PastoralDomainCommunityAppId, tt.AutoReplyItemId }); .HasKey(tt => new { tt.PastoralDomainCommunityAppId, tt.AutoReplyItemId });
modelBuilder.Entity<PastoralDomainAutoReplys>() modelBuilder.Entity<PastoralDomainAutoReplys>()
.HasOne(tt => tt.PastoralDomain) .HasOne(tt => tt.PastoralDomain)
.WithMany(t=>t.AutoReplyItemRelations) .WithMany(t => t.AutoReplyItemRelations)
.HasForeignKey(tt=>tt.PastoralDomainCommunityAppId) .HasForeignKey(tt => tt.PastoralDomainCommunityAppId)
.HasPrincipalKey(tt=>tt.CommunityAppId); .HasPrincipalKey(tt => tt.CommunityAppId);
//modelBuilder.Entity<PastoralDomainMembers>() //modelBuilder.Entity<PastoralDomainMembers>()
// .HasOne(t => t.PastoralDomain) // .HasOne(t => t.PastoralDomain)
@ -130,7 +135,10 @@ namespace Church.Net.DAL.EF
public DbSet<LogInfo> LogInfos { get; set; } public DbSet<LogInfo> LogInfos { get; set; }
public DbSet<AutoReplyItem> AutoReplyItems { get; set; } public DbSet<AutoReplyItem> AutoReplyItems { get; set; }
public DbSet<AddressInfo> AddressInfos { get; set; } public DbSet<AddressInfo> AddressInfos { get; set; }
public DbSet<LineMessageClient> LineMessageClients { get; set; }
public DbSet<LineMessagingAccount> LineMessagingAccounts { get; set; }
#endregion #endregion

View File

@ -0,0 +1,210 @@
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Transactions;
using System;
using Church.Net.DAL.EF;
using System.Linq;
using Church.Net.Utility;
using System.Threading.Tasks;
using Church.Net.Entity.Interface;
using System.ComponentModel.DataAnnotations;
using System.Reflection;
using static Microsoft.EntityFrameworkCore.DbLoggerCategory;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
namespace Church.Net.DAL.EFCoreDBF
{
public class CrudDALCBase1<T> : ICrudDAL<T> where T : class, IEntity, new()
{
private readonly ChurchNetContext dbContext;
public CrudDALCBase1(DatabaseOptions databaseOptions)
{
this.dbContext = databaseOptions.GetDbContext();
InitKeyProperty();
}
public IQueryable<T> GetDbSet()
{
//var result = (DbSet<T>)typeof(ChurchNetContext).GetMethod("Set").MakeGenericMethod(typeof(T)).Invoke(dbContext, null);
return dbContext.Set<T>().AsNoTracking();
//return result;
}
public virtual T First(Func<T, bool> filter = null)
{
return GetDbSet().Where(filter ?? (s => true)).FirstOrDefault();
}
public virtual T GetById(string Id)
{
return this.GetQuery(new string[] { Id }).FirstOrDefault();
}
//public virtual T GetByRefndx(string refndx)
//{
// return MapDBModelToEntity(GetFirstDBModelByRefndx<ST>(refndx, this.actionScreen));
//}
public virtual IEnumerable<T> GetAll(Func<T, bool> filter = null)
{
//var dbObjs = GetDbSet().ToArray();
//IEnumerable<T> list = GetDbSet().Where(filter ?? (s => true)).ToList();
return GetDbSet().AsNoTracking().Where(filter ?? (s => true)).ToList();
}
public virtual int Create(T entity)
{
this.CheckKeyIsEmpty(entity);
this.ConvertUTCTime(entity);
dbContext.Add(entity);
return dbContext.SaveChanges();
}
public virtual Task<int> CreateAsync(T entity)
{
this.CheckKeyIsEmpty(entity);
this.ConvertUTCTime(entity);
dbContext.Add(entity);
//CreateDone(entity, newDbObj);
return dbContext.SaveChangesAsync();
}
public int CreateOrUpdate(T entity)
{
int result = 0;
this.ConvertUTCTime(entity);
if (CheckExist(entity))
{
result = this.Update(entity);
}
else
{
result = this.Create(entity);
}
return result;
}
public virtual int Update(T entity)
{
//if (!this.CheckExist(entity))
//{
// throw new ArgumentNullException("the Id is not exist.");
//}
this.ConvertUTCTime(entity);
dbContext.Update(entity);
return dbContext.SaveChanges();
}
public virtual void CreateDone(T entity)
{
}
public virtual void UpdateDone(T entity)
{
}
public virtual int UpdateRange(IEnumerable<T> entities)
{
dbContext.UpdateRange(entities);
return dbContext.SaveChanges();
}
public virtual int Delete(T obj)
{
dbContext.Remove(obj);
return dbContext.SaveChanges();
}
public int Delete(Func<T, bool> filter)
{
var list = GetDbSet().Where(filter).ToList();
foreach (var item in list)
{
dbContext.Remove(item);
}
return dbContext.SaveChanges();
}
public virtual bool CheckExist(T obj)
{
//var query = GetDbSet().AsQueryable();
var query = GetAll();
List<PropertyInfo> props = new List<PropertyInfo>();
for (int i = 0; i < keyProps.Count; i++)
{
var prop = keyProps[i];
props.Add(prop);
var value = prop.GetValue(obj)?.ToString();
query = query.Where(e => prop.GetValue(e)?.ToString() == value).ToList();
}
return query.Any();
}
private void ConvertUTCTime(T entity)
{
var props = typeof(T).GetProperties();
foreach (var prop in props)
{
if (prop.PropertyType == typeof(DateTime))
{
//do stuff like prop.SetValue(t, DateTime.Now, null);
DateTime utcTime = ((DateTime)prop.GetValue(entity)).ToUniversalTime();
prop.SetValue(entity, utcTime, null);
}
}
}
private List<PropertyInfo> keyProps;
protected virtual void InitKeyProperty()
{
keyProps = typeof(T).GetProperties().Where(
prop => Attribute.IsDefined(prop, typeof(KeyAttribute))).OrderBy(prop =>
prop.GetCustomAttribute<ColumnAttribute>().Order
)
.ToList();
}
protected IQueryable<T> GetQuery(IEnumerable<string> Ids)
{
var query = GetDbSet().AsQueryable();
for (int i = 0; i < keyProps.Count; i++)
{
query = query.Where(e => keyProps[i].GetValue(e).ToString() == Ids.ElementAt(i));
}
return query;
}
protected virtual void CheckKeyIsEmpty(T entity)
{
if (string.IsNullOrWhiteSpace(entity.Id) || entity.Id.Length <= 3)
{
entity.Id = StringHelper.Get33BaseGuid();
}
}
public void Dispose()
{
throw new NotImplementedException();
}
}
}

View File

@ -17,24 +17,34 @@ namespace Church.Net.DAL.EFCoreDBF
{ {
public class CombinedKeyCrudDALCBase<T> : ICombinedKeyCrudDAL<T> where T : class, Church.Net.Entity.Interface.ICombinedKeyEntity, new() public class CombinedKeyCrudDALCBase<T> : ICombinedKeyCrudDAL<T> where T : class, Church.Net.Entity.Interface.ICombinedKeyEntity, new()
{ {
private readonly ChurchNetContext dbContext; private readonly DatabaseOptions databaseOptions;
public CombinedKeyCrudDALCBase(ChurchNetContext dbContext) public CombinedKeyCrudDALCBase(DatabaseOptions databaseOptions)
{ {
this.dbContext = dbContext; this.databaseOptions = databaseOptions;
InitKeyProperty(); InitKeyProperty();
} }
public DbSet<T> GetDbSet() public IQueryable<T> GetDbSet()
{ {
//var result = (DbSet<T>)typeof(ChurchNetContext).GetMethod("Set").MakeGenericMethod(typeof(T)).Invoke(dbContext, null); //var result = (DbSet<T>)typeof(ChurchNetContext).GetMethod("Set").MakeGenericMethod(typeof(T)).Invoke(dbContext, null);
return (DbSet<T>)dbContext.Set<T>(); return databaseOptions.GetDbContext().Set<T>().AsNoTracking();
//return result; //return result;
} }
public ChurchNetContext GetDbContext()
{
//var result = (DbSet<T>)typeof(ChurchNetContext).GetMethod("Set").MakeGenericMethod(typeof(T)).Invoke(dbContext, null);
return databaseOptions.GetDbContext();//.Set<T>().AsNoTracking();
//return result;
}
public virtual T First(Func<T, bool> filter = null) public virtual T First(Func<T, bool> filter = null)
{ {
return GetDbSet().Where(filter ?? (s => true)).FirstOrDefault(); using (var dbContext = GetDbContext())
{
return dbContext.Set<T>().Where(filter ?? (s => true)).FirstOrDefault();
}
} }
public virtual T GetById(IEnumerable<string> Ids) public virtual T GetById(IEnumerable<string> Ids)
@ -60,18 +70,25 @@ namespace Church.Net.DAL.EFCoreDBF
{ {
this.CheckCombinedKeyIsEmpty(entity); this.CheckCombinedKeyIsEmpty(entity);
this.ConvertUTCTime(entity); this.ConvertUTCTime(entity);
dbContext.Add(entity);
return dbContext.SaveChanges(); using (var dbContext = GetDbContext())
{
dbContext.Add(entity);
return dbContext.SaveChanges();
}
} }
public virtual Task<int> CreateAsync(T entity) public virtual Task<int> CreateAsync(T entity)
{ {
this.CheckCombinedKeyIsEmpty(entity); this.CheckCombinedKeyIsEmpty(entity);
this.ConvertUTCTime(entity); this.ConvertUTCTime(entity);
dbContext.Add(entity); using (var dbContext = GetDbContext())
{
dbContext.Add(entity);
//CreateDone(entity, newDbObj); //CreateDone(entity, newDbObj);
return dbContext.SaveChangesAsync(); return dbContext.SaveChangesAsync();
}
} }
@ -99,9 +116,12 @@ namespace Church.Net.DAL.EFCoreDBF
//} //}
this.ConvertUTCTime(entity); this.ConvertUTCTime(entity);
dbContext.Update(entity); using (var dbContext = GetDbContext())
{
dbContext.Update(entity);
return dbContext.SaveChanges(); return dbContext.SaveChanges();
}
} }
@ -116,15 +136,21 @@ namespace Church.Net.DAL.EFCoreDBF
public virtual int UpdateRange(IEnumerable<T> entities) public virtual int UpdateRange(IEnumerable<T> entities)
{ {
dbContext.UpdateRange(entities); using (var dbContext = GetDbContext())
{
dbContext.UpdateRange(entities);
return dbContext.SaveChanges(); return dbContext.SaveChanges();
}
} }
public virtual int Delete(T obj) public virtual int Delete(T obj)
{ {
dbContext.Remove(obj); using (var dbContext = GetDbContext())
return dbContext.SaveChanges(); {
dbContext.Remove(obj);
return dbContext.SaveChanges();
}
} }
public virtual int Delete(IEnumerable<string> combinedKeyIds) public virtual int Delete(IEnumerable<string> combinedKeyIds)
@ -136,11 +162,14 @@ namespace Church.Net.DAL.EFCoreDBF
public int Delete(Func<T, bool> filter) public int Delete(Func<T, bool> filter)
{ {
var list = GetDbSet().Where(filter).ToList(); var list = GetDbSet().Where(filter).ToList();
foreach (var item in list) using (var dbContext = GetDbContext())
{ {
dbContext.Remove(item); foreach (var item in list)
{
dbContext.Remove(item);
}
return dbContext.SaveChanges();
} }
return dbContext.SaveChanges();
} }
public virtual bool CheckExist(T obj) public virtual bool CheckExist(T obj)
@ -189,13 +218,16 @@ namespace Church.Net.DAL.EFCoreDBF
private IQueryable<T> GetQuery(IEnumerable<string> Ids) private IQueryable<T> GetQuery(IEnumerable<string> Ids)
{ {
var query = GetDbSet().AsQueryable(); using (var dbContext = GetDbContext())
for (int i = 0; i < keyProps.Count; i++)
{ {
query = query.Where(e => keyProps[i].GetValue(e).ToString() == Ids.ElementAt(i)); var query = dbContext.Set<T>().AsQueryable();
for (int i = 0; i < keyProps.Count; i++)
{
query = query.Where(e => keyProps[i].GetValue(e).ToString() == Ids.ElementAt(i));
}
return query;
} }
return query;
} }
private void CheckCombinedKeyIsEmpty(T entity) private void CheckCombinedKeyIsEmpty(T entity)
{ {

View File

@ -12,28 +12,37 @@ namespace Church.Net.DAL.EFCoreDBF
{ {
public class CrudDALCBase<T> : ICrudDAL<T> where T : class, Church.Net.Entity.Interface.IEntity, new() public class CrudDALCBase<T> : ICrudDAL<T> where T : class, Church.Net.Entity.Interface.IEntity, new()
{ {
private readonly ChurchNetContext dbContext; private readonly DatabaseOptions databaseOptions;
public CrudDALCBase(ChurchNetContext dbContext) //private readonly ChurchNetContext dbContext;
public CrudDALCBase(DatabaseOptions databaseOptions)
{ {
this.dbContext = dbContext; this.databaseOptions = databaseOptions;
//this.dbContext = databaseOptions.GetDbContext();
} }
public DbSet<T> GetDbSet() public ChurchNetContext GetDbContext()
{ {
//var result = (DbSet<T>)typeof(ChurchNetContext).GetMethod("Set").MakeGenericMethod(typeof(T)).Invoke(dbContext, null); //var result = (DbSet<T>)typeof(ChurchNetContext).GetMethod("Set").MakeGenericMethod(typeof(T)).Invoke(dbContext, null);
return (DbSet<T>)dbContext.Set<T>(); return databaseOptions.GetDbContext();//.Set<T>().AsNoTracking();
//return result; //return result;
} }
public virtual T First(Func<T, bool> filter = null) public virtual T First(Func<T, bool> filter = null)
{ {
return GetDbSet().Where(filter ?? (s => true)).FirstOrDefault(); using (var dbContext = GetDbContext())
{
return dbContext.Set<T>().Where(filter ?? (s => true)).FirstOrDefault();
}
} }
public virtual T GetById(string Id) public virtual T GetById(string Id)
{ {
return GetDbSet().FirstOrDefault(e => e.Id == Id); using (var dbContext = GetDbContext())
{
return dbContext.Set<T>().FirstOrDefault(e => e.Id == Id);
}
} }
//public virtual T GetByRefndx(string refndx) //public virtual T GetByRefndx(string refndx)
@ -43,41 +52,56 @@ namespace Church.Net.DAL.EFCoreDBF
public virtual IEnumerable<T> GetAll(Func<T, bool> filter = null) public virtual IEnumerable<T> GetAll(Func<T, bool> filter = null)
{ {
//var dbObjs = GetDbSet().ToArray(); using (var dbContext = GetDbContext())
{
return dbContext.Set<T>().Where(filter ?? (s => true)).ToList();
}
//var dbObjs = GetDbContext().ToArray();
//IEnumerable<T> list = GetDbSet().Where(filter ?? (s => true)).ToList(); //IEnumerable<T> list = GetDbContext().Where(filter ?? (s => true)).ToList();
return GetDbSet().Where(filter ?? (s => true)).ToList();
} }
public virtual IEnumerable<T> GetAllById(IEnumerable<string> Ids) public virtual IEnumerable<T> GetAllById(IEnumerable<string> Ids)
{ {
var RowIds = Ids.Select(i => i.ToString()); using (var dbContext = GetDbContext())
{
var RowIds = Ids.Select(i => i.ToString());
//return GetDbSet().Where(e => RowIds.Any(id => id == e.Id)); //return GetDbContext().Where(e => RowIds.Any(id => id == e.Id));
//var list = new List<T>(); //var list = new List<T>();
var dbObjs = GetDbSet().Where(e => RowIds.Any(id => id == e.Id)).ToArray();
return dbContext.Set<T>().Where(e => RowIds.Any(id => id == e.Id)).ToArray();
}
}
private bool needGenId(T entity)
{
return string.IsNullOrWhiteSpace(entity.Id) || entity.Id.Length <= 3;
return dbObjs.ToList();
} }
public virtual int Create(T entity) public virtual int Create(T entity)
{ {
if (string.IsNullOrEmpty(entity.Id)) if (needGenId(entity))
{ {
entity.Id = StringHelper.Get33BaseGuid(); entity.Id = StringHelper.Get33BaseGuid();
} }
this.ConvertUTCTime(entity); this.ConvertUTCTime(entity);
dbContext.Add(entity);
return dbContext.SaveChanges(); using (var dbContext = GetDbContext())
{
dbContext.Add(entity);
return dbContext.SaveChanges();
}
} }
public virtual Task<int> CreateAsync(T entity) public virtual Task<int> CreateAsync(T entity)
{ {
int result = 0; int result = 0;
this.ConvertUTCTime(entity); this.ConvertUTCTime(entity);
if (string.IsNullOrEmpty(entity.Id)) if (needGenId(entity))
{ {
entity.Id = StringHelper.Get33BaseGuid(); entity.Id = StringHelper.Get33BaseGuid();
} }
@ -88,10 +112,13 @@ namespace Church.Net.DAL.EFCoreDBF
//newDbObj.RowId = entity.Id.ToString(); //newDbObj.RowId = entity.Id.ToString();
//result = Add(newDbObj) ? 1 : 0; //result = Add(newDbObj) ? 1 : 0;
} }
dbContext.Add(entity); using (var dbContext = GetDbContext())
{
dbContext.Add(entity);
//CreateDone(entity, newDbObj); //CreateDone(entity, newDbObj);
return dbContext.SaveChangesAsync(); return dbContext.SaveChangesAsync();
}
} }
public virtual string CreateReturnId(T entity) public virtual string CreateReturnId(T entity)
{ {
@ -106,40 +133,45 @@ namespace Church.Net.DAL.EFCoreDBF
}; };
} }
public int CreateOrUpdate(T entity, out string id) public int CreateOrUpdate(T entity)
{ {
id = null;
this.ConvertUTCTime(entity); this.ConvertUTCTime(entity);
if (CheckExist(entity))
using (var dbContext = GetDbContext())
{ {
dbContext.Update(entity); if (CheckExist(entity))
}
else
{
if (string.IsNullOrEmpty(entity.Id))
{ {
entity.Id = StringHelper.Get33BaseGuid(); dbContext.Update(entity);
} }
id = entity.Id; else
dbContext.Add(entity); {
if (needGenId(entity))
{
entity.Id = StringHelper.Get33BaseGuid();
}
dbContext.Add(entity);
}
return dbContext.SaveChanges();
} }
return dbContext.SaveChanges();
} }
public virtual int Update(T entity) public virtual int Update(T entity)
{ {
using (var dbContext = GetDbContext())
var dbObj = GetDbSet().FirstOrDefault(e => e.Id == entity.Id);
if (dbObj == null)
{ {
throw new ArgumentNullException("the Id is not exist."); //var dbObj = dbContext.Set<T>().Any(e => e.Id == entity.Id);
if (!dbContext.Set<T>().Any(e => e.Id == entity.Id))
{
throw new ArgumentNullException("the Id is not exist.");
}
this.ConvertUTCTime(entity);
dbContext.Update(entity);
return dbContext.SaveChanges();
} }
this.ConvertUTCTime(entity);
dbContext.Update(dbObj);
return dbContext.SaveChanges();
} }
public virtual void CreateDone(T entity) public virtual void CreateDone(T entity)
@ -157,31 +189,44 @@ namespace Church.Net.DAL.EFCoreDBF
{ {
this.ConvertUTCTime(entity); this.ConvertUTCTime(entity);
} }
dbContext.UpdateRange(entities); using (var dbContext = GetDbContext())
{
dbContext.UpdateRange(entities);
return dbContext.SaveChanges(); return dbContext.SaveChanges();
}
} }
public virtual int Delete(T obj) public virtual int Delete(T obj)
{ {
dbContext.Remove(GetDbSet().FirstOrDefault(e => e.Id == obj.Id.ToString())); using (var dbContext = GetDbContext())
return dbContext.SaveChanges(); {
dbContext.Remove(dbContext.Set<T>().FirstOrDefault(e => e.Id == obj.Id.ToString()));
return dbContext.SaveChanges();
}
} }
public int Delete(Func<T, bool> filter) public int Delete(Func<T, bool> filter)
{ {
var list = GetDbSet().Where(filter).ToList(); using (var dbContext = GetDbContext())
if (list.Count > 0)
{ {
dbContext.RemoveRange(list);
return dbContext.SaveChanges(); var list = dbContext.Set<T>().Where(filter).ToList();
if (list.Count > 0)
{
dbContext.RemoveRange(list);
return dbContext.SaveChanges();
}
return 0;
} }
return 0;
} }
public virtual bool CheckExist(T obj) public virtual bool CheckExist(T obj)
{ {
return GetDbSet().Any(e => e.Id == obj.Id); using (var dbContext = GetDbContext())
{
return dbContext.Set<T>().Any(e => e.Id == obj.Id);
}
} }
private void ConvertUTCTime(T entity) private void ConvertUTCTime(T entity)
@ -193,12 +238,41 @@ namespace Church.Net.DAL.EFCoreDBF
if (prop.PropertyType == typeof(DateTime)) if (prop.PropertyType == typeof(DateTime))
{ {
//do stuff like prop.SetValue(t, DateTime.Now, null); //do stuff like prop.SetValue(t, DateTime.Now, null);
DateTime utcTime = ((DateTime)prop.GetValue(entity)).ToUniversalTime(); DateTime localTime = ((DateTime)prop.GetValue(entity));
if (localTime.Kind != DateTimeKind.Utc)
{
//localTime= DateTime.SpecifyKind(localTime, DateTimeKind.Local);
localTime = new DateTime(localTime.Year, localTime.Month, localTime.Day,
localTime.Hour, localTime.Minute, localTime.Second, localTime.Millisecond);
}
DateTime utcTime = localTime.ToUniversalTime();
prop.SetValue(entity, utcTime, null); prop.SetValue(entity, utcTime, null);
} }
else if (prop.PropertyType == typeof(DateTime?))
{
DateTime? localTime = ((DateTime?)prop.GetValue(entity));
if (localTime.HasValue)
{
if (localTime.Value.Kind != DateTimeKind.Utc)
{
//localTime = DateTime.SpecifyKind(localTime.Value, DateTimeKind.Local);
localTime = new DateTime(localTime.Value.Year, localTime.Value.Month, localTime.Value.Day,
localTime.Value.Hour, localTime.Value.Minute, localTime.Value.Second,
localTime.Value.Millisecond, DateTimeKind.Local);
}
DateTime? utcTime = localTime.Value.ToUniversalTime();
prop.SetValue(entity, utcTime, null);
}
}
} }
} }
public IQueryable<T> GetDbSet()
{
return databaseOptions.GetDbContext().Set<T>().AsNoTracking();
}
} }

View File

@ -0,0 +1,16 @@
using Church.Net.DAL.EF;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Church.Net.DAL.EFCoreDBF
{
public class DatabaseOptions
{
public string ConnectionString { get; set; }
public ChurchNetContext GetDbContext() => new ChurchNetContext(ConnectionString);
}
}

View File

@ -9,19 +9,18 @@ using System.Threading.Tasks;
namespace Church.Net.DAL.EFCoreDBF namespace Church.Net.DAL.EFCoreDBF
{ {
public interface ICrudDAL<T> where T:class,IEntity public interface ICrudDAL<T> where T : class, IEntity
{ {
DbSet<T> GetDbSet(); IQueryable<T> GetDbSet();
T First(Func<T, bool> filter = null); T First(Func<T, bool> filter = null);
T GetById(string Id); T GetById(string Id);
IEnumerable<T> GetAll(Func<T, bool> filter = null); IEnumerable<T> GetAll(Func<T, bool> filter = null);
IEnumerable<T> GetAllById(IEnumerable<string> Ids); //IEnumerable<T> GetAllById(IEnumerable<string> Ids);
int Create(T entity); int Create(T entity);
Task<int> CreateAsync(T entity); Task<int> CreateAsync(T entity);
string CreateReturnId(T entity);
int CreateOrUpdate(T entity, out string id); int CreateOrUpdate(T entity);
int Update(T entity); int Update(T entity);
void CreateDone(T entity); void CreateDone(T entity);
void UpdateDone(T entity); void UpdateDone(T entity);
@ -35,9 +34,9 @@ namespace Church.Net.DAL.EFCoreDBF
} }
public interface ICombinedKeyCrudDAL<T> where T : class, ICombinedKeyEntity public interface ICombinedKeyCrudDAL<T> where T : class
{ {
DbSet<T> GetDbSet(); IQueryable<T> GetDbSet();
T First(Func<T, bool> filter = null); T First(Func<T, bool> filter = null);
T GetById(IEnumerable<string> combinedKeyIds); T GetById(IEnumerable<string> combinedKeyIds);

View File

@ -0,0 +1,798 @@
// <auto-generated />
using System;
using Church.Net.DAL.EF;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace Church.Net.DAL.EFCoreDBF.Migrations
{
[DbContext(typeof(ChurchNetContext))]
[Migration("20220914151710_AddTaskToHappinessWeek")]
partial class AddTaskToHappinessWeek
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "6.0.8")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("Church.Net.Entity.AddressInfo", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Address")
.HasColumnType("text");
b.Property<string>("City")
.HasColumnType("text");
b.Property<string>("State")
.HasColumnType("text");
b.Property<string>("Zip")
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("AddressInfos");
});
modelBuilder.Entity("Church.Net.Entity.AutoReplyItem", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Command")
.HasColumnType("text");
b.Property<string>("Content")
.HasColumnType("text");
b.Property<string>("Description")
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("AutoReplyItems");
});
modelBuilder.Entity("Church.Net.Entity.Career", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Name")
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.HasKey("Id");
b.ToTable("Careers");
});
modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEvent", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Address")
.HasColumnType("text");
b.Property<DateTime>("Time")
.HasColumnType("timestamp with time zone");
b.HasKey("Id");
b.ToTable("CellGroupRoutineEvents");
});
modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEventAttendee", b =>
{
b.Property<string>("EventId")
.HasColumnType("text")
.HasColumnOrder(0);
b.Property<string>("Id")
.HasColumnType("text")
.HasColumnOrder(1);
b.Property<string>("Comment")
.HasColumnType("text");
b.Property<bool>("JoinPotluck")
.HasColumnType("boolean");
b.Property<string>("Name")
.HasColumnType("text");
b.Property<string>("PotluckItem")
.HasColumnType("text");
b.HasKey("EventId", "Id");
b.ToTable("CellGroupRoutineEventAttendees");
});
modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEventPrayer", b =>
{
b.Property<string>("EventId")
.HasColumnType("text")
.HasColumnOrder(0);
b.Property<string>("MemberId")
.HasColumnType("text")
.HasColumnOrder(1);
b.Property<string>("Comment")
.HasColumnType("text");
b.Property<string>("Prayer")
.HasColumnType("text");
b.HasKey("EventId", "MemberId");
b.ToTable("CellGroupRoutineEventPrayers");
});
modelBuilder.Entity("Church.Net.Entity.FamilyMember", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Address")
.HasMaxLength(500)
.HasColumnType("character varying(500)");
b.Property<string>("AvatarImage")
.HasColumnType("text");
b.Property<bool>("Baptized")
.HasColumnType("boolean");
b.Property<DateTime?>("Birthday")
.HasColumnType("timestamp with time zone");
b.Property<string>("CareerId")
.HasColumnType("text");
b.Property<string>("Comment")
.HasColumnType("text");
b.Property<string>("ComunityAppId")
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<DateTime?>("DateOfBaptized")
.HasColumnType("timestamp with time zone");
b.Property<DateTime?>("DateOfWalkIn")
.HasColumnType("timestamp with time zone");
b.Property<string>("Email")
.HasColumnType("text");
b.Property<string>("FirstName")
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<int>("Gender")
.HasColumnType("integer");
b.Property<string>("LastName")
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<bool>("Married")
.HasColumnType("boolean");
b.Property<string>("Password")
.HasColumnType("text");
b.Property<int>("Role")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("CareerId");
b.ToTable("FamilyMembers");
});
modelBuilder.Entity("Church.Net.Entity.FamilyMemberOAuth", b =>
{
b.Property<string>("FamilyMemberId")
.HasColumnType("text")
.HasColumnOrder(0);
b.Property<string>("OAuthType")
.HasColumnType("text")
.HasColumnOrder(1);
b.Property<string>("OAuthAccessToken")
.HasColumnType("text");
b.HasKey("FamilyMemberId", "OAuthType");
b.ToTable("FamilyMemberOAuths");
});
modelBuilder.Entity("Church.Net.Entity.HappinessBEST", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Email")
.HasColumnType("text");
b.Property<string>("GroupId")
.HasColumnType("text");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Phone")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("GroupId");
b.ToTable("HappinessBESTs");
});
modelBuilder.Entity("Church.Net.Entity.HappinessGroup", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Address")
.HasColumnType("text");
b.Property<DateTime>("BeginTime")
.HasColumnType("timestamp with time zone");
b.Property<string>("CityAndZipCode")
.HasColumnType("text");
b.Property<string>("InvitationText")
.HasColumnType("text");
b.Property<string>("Name")
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("HappinessGroups");
});
modelBuilder.Entity("Church.Net.Entity.HappinessTask", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Content")
.HasColumnType("text");
b.Property<string>("Tasker")
.HasColumnType("text");
b.Property<int>("Type")
.HasColumnType("integer");
b.Property<string>("WeekId")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("WeekId");
b.ToTable("HappinessTask");
});
modelBuilder.Entity("Church.Net.Entity.HappinessWeek", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Address")
.HasColumnType("text");
b.Property<string>("CityAndZipCode")
.HasColumnType("text");
b.Property<string>("Comment")
.HasColumnType("text");
b.Property<DateTime>("Date")
.HasColumnType("timestamp with time zone");
b.Property<string>("GroupId")
.HasColumnType("text");
b.Property<string>("InvitationText")
.HasColumnType("text");
b.Property<int>("SEQ")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("GroupId");
b.ToTable("HappinessWeeks");
});
modelBuilder.Entity("Church.Net.Entity.LogInfo", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("DetailMessage")
.HasColumnType("text");
b.Property<int>("Level")
.HasColumnType("integer");
b.Property<string>("Message")
.HasColumnType("text");
b.Property<string>("Source")
.HasColumnType("text");
b.Property<string>("StackTrace")
.HasColumnType("text");
b.Property<DateTime>("Time")
.HasColumnType("timestamp with time zone");
b.Property<int>("TrackNo")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("TrackNo"));
b.Property<string>("Url")
.HasColumnType("text");
b.Property<string>("UserId")
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("LogInfos");
});
modelBuilder.Entity("Church.Net.Entity.NewVisitor", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Address")
.HasMaxLength(500)
.HasColumnType("character varying(500)");
b.Property<DateTime?>("BirthDate")
.HasColumnType("timestamp with time zone");
b.Property<string>("ComunityAppId")
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<string>("Email")
.HasMaxLength(150)
.HasColumnType("character varying(150)");
b.Property<string>("FirstName")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<int>("Gender")
.HasColumnType("integer");
b.Property<string>("LastName")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<string>("Note")
.HasColumnType("text");
b.Property<string>("Phone")
.IsRequired()
.HasMaxLength(150)
.HasColumnType("character varying(150)");
b.Property<int?>("ReligionId")
.HasColumnType("integer");
b.Property<DateTime>("VisitingDate")
.HasColumnType("timestamp with time zone");
b.HasKey("Id");
b.HasIndex("ReligionId");
b.ToTable("NewVisitors");
});
modelBuilder.Entity("Church.Net.Entity.PastoralDomain", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("CommunityAppId")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Description")
.HasColumnType("text");
b.Property<string>("Image1")
.HasColumnType("text");
b.Property<string>("Image2")
.HasColumnType("text");
b.Property<string>("Image3")
.HasColumnType("text");
b.Property<string>("Image4")
.HasColumnType("text");
b.Property<string>("Image5")
.HasColumnType("text");
b.Property<string>("LeaderMemberId")
.HasColumnType("text");
b.Property<string>("LogoImage")
.HasColumnType("text");
b.Property<string>("Name")
.HasColumnType("text");
b.Property<string>("ServiceAddressId")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("LeaderMemberId");
b.HasIndex("ServiceAddressId");
b.ToTable("PastoralDomains");
});
modelBuilder.Entity("Church.Net.Entity.PastoralDomainAutoReplys", b =>
{
b.Property<string>("PastoralDomainCommunityAppId")
.HasColumnType("text")
.HasColumnOrder(0);
b.Property<string>("AutoReplyItemId")
.HasColumnType("text")
.HasColumnOrder(1);
b.HasKey("PastoralDomainCommunityAppId", "AutoReplyItemId");
b.HasIndex("AutoReplyItemId");
b.ToTable("PastoralDomainAutoReplys");
});
modelBuilder.Entity("Church.Net.Entity.PastoralDomainMembers", b =>
{
b.Property<string>("PastoralDomainId")
.HasColumnType("text")
.HasColumnOrder(0);
b.Property<string>("FamilyMemberId")
.HasColumnType("text")
.HasColumnOrder(1);
b.HasKey("PastoralDomainId", "FamilyMemberId");
b.HasIndex("FamilyMemberId");
b.ToTable("PastoralDomainMembers");
});
modelBuilder.Entity("Church.Net.Entity.Religion", b =>
{
b.Property<int>("ReligionId")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("ReligionId"));
b.Property<string>("Name")
.HasColumnType("text");
b.HasKey("ReligionId");
b.ToTable("Religions");
});
modelBuilder.Entity("Church.Net.Entity.Vocabulary", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("DefinitionCh")
.IsRequired()
.HasColumnType("text");
b.Property<string>("DefinitionEn")
.IsRequired()
.HasColumnType("text");
b.Property<int>("FlashCardTimes")
.HasColumnType("integer");
b.Property<string>("ImagesUrl")
.HasColumnType("text");
b.Property<DateTime>("InsertDate")
.HasColumnType("timestamp with time zone");
b.Property<string>("NounPlural")
.HasColumnType("text");
b.Property<int>("PartOfSpeech")
.HasColumnType("integer");
b.Property<bool>("PracticeApply")
.HasColumnType("boolean");
b.Property<DateTime>("PracticeDate")
.HasColumnType("timestamp with time zone");
b.Property<bool>("PracticeMemorized")
.HasColumnType("boolean");
b.Property<bool>("PracticeReview")
.HasColumnType("boolean");
b.Property<bool>("PracticeSelect")
.HasColumnType("boolean");
b.Property<string>("PracticeSentence")
.HasColumnType("text");
b.Property<int>("PracticeStage")
.HasColumnType("integer");
b.Property<bool>("PracticeVisualize")
.HasColumnType("boolean");
b.Property<string>("VerbParticiple")
.HasColumnType("text");
b.Property<string>("VerbPast")
.HasColumnType("text");
b.Property<string>("Word")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Vocabulary");
});
modelBuilder.Entity("Church.Net.Entity.WhoIsSpy", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Answer1Chs")
.HasColumnType("text");
b.Property<string>("Answer1Cht")
.HasColumnType("text");
b.Property<string>("Answer1En")
.HasColumnType("text");
b.Property<string>("Answer2Chs")
.HasColumnType("text");
b.Property<string>("Answer2Cht")
.HasColumnType("text");
b.Property<string>("Answer2En")
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("WhoIsSpy");
});
modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEventAttendee", b =>
{
b.HasOne("Church.Net.Entity.CellGroupRoutineEvent", "CellGroupRoutineEvent")
.WithMany("Attendees")
.HasForeignKey("EventId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("CellGroupRoutineEvent");
});
modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEventPrayer", b =>
{
b.HasOne("Church.Net.Entity.CellGroupRoutineEvent", "CellGroupRoutineEvent")
.WithMany("Prayers")
.HasForeignKey("EventId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("CellGroupRoutineEvent");
});
modelBuilder.Entity("Church.Net.Entity.FamilyMember", b =>
{
b.HasOne("Church.Net.Entity.Career", "Career")
.WithMany()
.HasForeignKey("CareerId");
b.Navigation("Career");
});
modelBuilder.Entity("Church.Net.Entity.FamilyMemberOAuth", b =>
{
b.HasOne("Church.Net.Entity.FamilyMember", null)
.WithMany("OAuthInfos")
.HasForeignKey("FamilyMemberId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Church.Net.Entity.HappinessBEST", b =>
{
b.HasOne("Church.Net.Entity.HappinessGroup", "HappinessGroup")
.WithMany("BestList")
.HasForeignKey("GroupId");
b.Navigation("HappinessGroup");
});
modelBuilder.Entity("Church.Net.Entity.HappinessTask", b =>
{
b.HasOne("Church.Net.Entity.HappinessWeek", "HappinessWeek")
.WithMany("Tasks")
.HasForeignKey("WeekId");
b.Navigation("HappinessWeek");
});
modelBuilder.Entity("Church.Net.Entity.HappinessWeek", b =>
{
b.HasOne("Church.Net.Entity.HappinessGroup", "HappinessGroup")
.WithMany("Weeks")
.HasForeignKey("GroupId");
b.Navigation("HappinessGroup");
});
modelBuilder.Entity("Church.Net.Entity.NewVisitor", b =>
{
b.HasOne("Church.Net.Entity.Religion", "Religion")
.WithMany()
.HasForeignKey("ReligionId");
b.Navigation("Religion");
});
modelBuilder.Entity("Church.Net.Entity.PastoralDomain", b =>
{
b.HasOne("Church.Net.Entity.FamilyMember", "Leader")
.WithMany()
.HasForeignKey("LeaderMemberId");
b.HasOne("Church.Net.Entity.AddressInfo", "ServiceAddress")
.WithMany()
.HasForeignKey("ServiceAddressId");
b.Navigation("Leader");
b.Navigation("ServiceAddress");
});
modelBuilder.Entity("Church.Net.Entity.PastoralDomainAutoReplys", b =>
{
b.HasOne("Church.Net.Entity.AutoReplyItem", "FamilyMember")
.WithMany("AutoReplyItemRelations")
.HasForeignKey("AutoReplyItemId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Church.Net.Entity.PastoralDomain", "PastoralDomain")
.WithMany("AutoReplyItemRelations")
.HasForeignKey("PastoralDomainCommunityAppId")
.HasPrincipalKey("CommunityAppId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("FamilyMember");
b.Navigation("PastoralDomain");
});
modelBuilder.Entity("Church.Net.Entity.PastoralDomainMembers", b =>
{
b.HasOne("Church.Net.Entity.FamilyMember", "FamilyMember")
.WithMany("PastoralDomains")
.HasForeignKey("FamilyMemberId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Church.Net.Entity.PastoralDomain", "PastoralDomain")
.WithMany("Members")
.HasForeignKey("PastoralDomainId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("FamilyMember");
b.Navigation("PastoralDomain");
});
modelBuilder.Entity("Church.Net.Entity.AutoReplyItem", b =>
{
b.Navigation("AutoReplyItemRelations");
});
modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEvent", b =>
{
b.Navigation("Attendees");
b.Navigation("Prayers");
});
modelBuilder.Entity("Church.Net.Entity.FamilyMember", b =>
{
b.Navigation("OAuthInfos");
b.Navigation("PastoralDomains");
});
modelBuilder.Entity("Church.Net.Entity.HappinessGroup", b =>
{
b.Navigation("BestList");
b.Navigation("Weeks");
});
modelBuilder.Entity("Church.Net.Entity.HappinessWeek", b =>
{
b.Navigation("Tasks");
});
modelBuilder.Entity("Church.Net.Entity.PastoralDomain", b =>
{
b.Navigation("AutoReplyItemRelations");
b.Navigation("Members");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,53 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Church.Net.DAL.EFCoreDBF.Migrations
{
public partial class AddTaskToHappinessWeek : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "Comment",
table: "HappinessWeeks",
type: "text",
nullable: true);
migrationBuilder.CreateTable(
name: "HappinessTask",
columns: table => new
{
Id = table.Column<string>(type: "text", nullable: false),
WeekId = table.Column<string>(type: "text", nullable: true),
Type = table.Column<int>(type: "integer", nullable: false),
Tasker = table.Column<string>(type: "text", nullable: true),
Content = table.Column<string>(type: "text", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_HappinessTask", x => x.Id);
table.ForeignKey(
name: "FK_HappinessTask_HappinessWeeks_WeekId",
column: x => x.WeekId,
principalTable: "HappinessWeeks",
principalColumn: "Id");
});
migrationBuilder.CreateIndex(
name: "IX_HappinessTask_WeekId",
table: "HappinessTask",
column: "WeekId");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "HappinessTask");
migrationBuilder.DropColumn(
name: "Comment",
table: "HappinessWeeks");
}
}
}

View File

@ -0,0 +1,823 @@
// <auto-generated />
using System;
using Church.Net.DAL.EF;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace Church.Net.DAL.EFCoreDBF.Migrations
{
[DbContext(typeof(ChurchNetContext))]
[Migration("20220929210007_AddLienClient")]
partial class AddLienClient
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "6.0.8")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("Church.Net.Entity.AddressInfo", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Address")
.HasColumnType("text");
b.Property<string>("City")
.HasColumnType("text");
b.Property<string>("State")
.HasColumnType("text");
b.Property<string>("Zip")
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("AddressInfos");
});
modelBuilder.Entity("Church.Net.Entity.AutoReplyItem", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Command")
.HasColumnType("text");
b.Property<string>("Content")
.HasColumnType("text");
b.Property<string>("Description")
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("AutoReplyItems");
});
modelBuilder.Entity("Church.Net.Entity.Career", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Name")
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.HasKey("Id");
b.ToTable("Careers");
});
modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEvent", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Address")
.HasColumnType("text");
b.Property<DateTime>("Time")
.HasColumnType("timestamp with time zone");
b.HasKey("Id");
b.ToTable("CellGroupRoutineEvents");
});
modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEventAttendee", b =>
{
b.Property<string>("EventId")
.HasColumnType("text")
.HasColumnOrder(0);
b.Property<string>("Id")
.HasColumnType("text")
.HasColumnOrder(1);
b.Property<string>("Comment")
.HasColumnType("text");
b.Property<bool>("JoinPotluck")
.HasColumnType("boolean");
b.Property<string>("Name")
.HasColumnType("text");
b.Property<string>("PotluckItem")
.HasColumnType("text");
b.HasKey("EventId", "Id");
b.ToTable("CellGroupRoutineEventAttendees");
});
modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEventPrayer", b =>
{
b.Property<string>("EventId")
.HasColumnType("text")
.HasColumnOrder(0);
b.Property<string>("MemberId")
.HasColumnType("text")
.HasColumnOrder(1);
b.Property<string>("Comment")
.HasColumnType("text");
b.Property<string>("Prayer")
.HasColumnType("text");
b.HasKey("EventId", "MemberId");
b.ToTable("CellGroupRoutineEventPrayers");
});
modelBuilder.Entity("Church.Net.Entity.FamilyMember", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Address")
.HasMaxLength(500)
.HasColumnType("character varying(500)");
b.Property<string>("AvatarImage")
.HasColumnType("text");
b.Property<bool>("Baptized")
.HasColumnType("boolean");
b.Property<DateTime?>("Birthday")
.HasColumnType("timestamp with time zone");
b.Property<string>("CareerId")
.HasColumnType("text");
b.Property<string>("Comment")
.HasColumnType("text");
b.Property<string>("ComunityAppId")
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<DateTime?>("DateOfBaptized")
.HasColumnType("timestamp with time zone");
b.Property<DateTime?>("DateOfWalkIn")
.HasColumnType("timestamp with time zone");
b.Property<string>("Email")
.HasColumnType("text");
b.Property<string>("FirstName")
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<int>("Gender")
.HasColumnType("integer");
b.Property<string>("LastName")
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<bool>("Married")
.HasColumnType("boolean");
b.Property<string>("Password")
.HasColumnType("text");
b.Property<int>("Role")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("CareerId");
b.ToTable("FamilyMembers");
});
modelBuilder.Entity("Church.Net.Entity.FamilyMemberOAuth", b =>
{
b.Property<string>("FamilyMemberId")
.HasColumnType("text")
.HasColumnOrder(0);
b.Property<string>("OAuthType")
.HasColumnType("text")
.HasColumnOrder(1);
b.Property<string>("OAuthAccessToken")
.HasColumnType("text");
b.HasKey("FamilyMemberId", "OAuthType");
b.ToTable("FamilyMemberOAuths");
});
modelBuilder.Entity("Church.Net.Entity.HappinessBEST", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Email")
.HasColumnType("text");
b.Property<string>("GroupId")
.HasColumnType("text");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Phone")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("GroupId");
b.ToTable("HappinessBESTs");
});
modelBuilder.Entity("Church.Net.Entity.HappinessGroup", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Address")
.HasColumnType("text");
b.Property<DateTime>("BeginTime")
.HasColumnType("timestamp with time zone");
b.Property<string>("CityAndZipCode")
.HasColumnType("text");
b.Property<string>("CommunityAppId")
.HasColumnType("text");
b.Property<string>("InvitationText")
.HasColumnType("text");
b.Property<string>("Name")
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("HappinessGroups");
});
modelBuilder.Entity("Church.Net.Entity.HappinessTask", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Content")
.HasColumnType("text");
b.Property<string>("Tasker")
.HasColumnType("text");
b.Property<int>("Type")
.HasColumnType("integer");
b.Property<string>("WeekId")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("WeekId");
b.ToTable("HappinessTask");
});
modelBuilder.Entity("Church.Net.Entity.HappinessWeek", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Address")
.HasColumnType("text");
b.Property<string>("CityAndZipCode")
.HasColumnType("text");
b.Property<string>("Comment")
.HasColumnType("text");
b.Property<DateTime>("Date")
.HasColumnType("timestamp with time zone");
b.Property<string>("GroupId")
.HasColumnType("text");
b.Property<string>("InvitationText")
.HasColumnType("text");
b.Property<int>("SEQ")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("GroupId");
b.ToTable("HappinessWeeks");
});
modelBuilder.Entity("Church.Net.Entity.LogInfo", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("DetailMessage")
.HasColumnType("text");
b.Property<int>("Level")
.HasColumnType("integer");
b.Property<string>("Message")
.HasColumnType("text");
b.Property<string>("Source")
.HasColumnType("text");
b.Property<string>("StackTrace")
.HasColumnType("text");
b.Property<DateTime>("Time")
.HasColumnType("timestamp with time zone");
b.Property<int>("TrackNo")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("TrackNo"));
b.Property<string>("Url")
.HasColumnType("text");
b.Property<string>("UserId")
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("LogInfos");
});
modelBuilder.Entity("Church.Net.Entity.Messenger.LineMessageClient", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("ClientId")
.HasColumnType("text");
b.Property<bool>("IsGroup")
.HasColumnType("boolean");
b.Property<bool>("IsManager")
.HasColumnType("boolean");
b.Property<string>("Name")
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("LineMessageClients");
});
modelBuilder.Entity("Church.Net.Entity.NewVisitor", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Address")
.HasMaxLength(500)
.HasColumnType("character varying(500)");
b.Property<DateTime?>("BirthDate")
.HasColumnType("timestamp with time zone");
b.Property<string>("ComunityAppId")
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<string>("Email")
.HasMaxLength(150)
.HasColumnType("character varying(150)");
b.Property<string>("FirstName")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<int>("Gender")
.HasColumnType("integer");
b.Property<string>("LastName")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<string>("Note")
.HasColumnType("text");
b.Property<string>("Phone")
.IsRequired()
.HasMaxLength(150)
.HasColumnType("character varying(150)");
b.Property<int?>("ReligionId")
.HasColumnType("integer");
b.Property<DateTime>("VisitingDate")
.HasColumnType("timestamp with time zone");
b.HasKey("Id");
b.HasIndex("ReligionId");
b.ToTable("NewVisitors");
});
modelBuilder.Entity("Church.Net.Entity.PastoralDomain", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("CommunityAppId")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Description")
.HasColumnType("text");
b.Property<string>("Image1")
.HasColumnType("text");
b.Property<string>("Image2")
.HasColumnType("text");
b.Property<string>("Image3")
.HasColumnType("text");
b.Property<string>("Image4")
.HasColumnType("text");
b.Property<string>("Image5")
.HasColumnType("text");
b.Property<string>("LeaderMemberId")
.HasColumnType("text");
b.Property<string>("LogoImage")
.HasColumnType("text");
b.Property<string>("Name")
.HasColumnType("text");
b.Property<string>("ServiceAddressId")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("LeaderMemberId");
b.HasIndex("ServiceAddressId");
b.ToTable("PastoralDomains");
});
modelBuilder.Entity("Church.Net.Entity.PastoralDomainAutoReplys", b =>
{
b.Property<string>("PastoralDomainCommunityAppId")
.HasColumnType("text")
.HasColumnOrder(0);
b.Property<string>("AutoReplyItemId")
.HasColumnType("text")
.HasColumnOrder(1);
b.HasKey("PastoralDomainCommunityAppId", "AutoReplyItemId");
b.HasIndex("AutoReplyItemId");
b.ToTable("PastoralDomainAutoReplys");
});
modelBuilder.Entity("Church.Net.Entity.PastoralDomainMembers", b =>
{
b.Property<string>("PastoralDomainId")
.HasColumnType("text")
.HasColumnOrder(0);
b.Property<string>("FamilyMemberId")
.HasColumnType("text")
.HasColumnOrder(1);
b.HasKey("PastoralDomainId", "FamilyMemberId");
b.HasIndex("FamilyMemberId");
b.ToTable("PastoralDomainMembers");
});
modelBuilder.Entity("Church.Net.Entity.Religion", b =>
{
b.Property<int>("ReligionId")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("ReligionId"));
b.Property<string>("Name")
.HasColumnType("text");
b.HasKey("ReligionId");
b.ToTable("Religions");
});
modelBuilder.Entity("Church.Net.Entity.Vocabulary", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("DefinitionCh")
.IsRequired()
.HasColumnType("text");
b.Property<string>("DefinitionEn")
.IsRequired()
.HasColumnType("text");
b.Property<int>("FlashCardTimes")
.HasColumnType("integer");
b.Property<string>("ImagesUrl")
.HasColumnType("text");
b.Property<DateTime>("InsertDate")
.HasColumnType("timestamp with time zone");
b.Property<string>("NounPlural")
.HasColumnType("text");
b.Property<int>("PartOfSpeech")
.HasColumnType("integer");
b.Property<bool>("PracticeApply")
.HasColumnType("boolean");
b.Property<DateTime>("PracticeDate")
.HasColumnType("timestamp with time zone");
b.Property<bool>("PracticeMemorized")
.HasColumnType("boolean");
b.Property<bool>("PracticeReview")
.HasColumnType("boolean");
b.Property<bool>("PracticeSelect")
.HasColumnType("boolean");
b.Property<string>("PracticeSentence")
.HasColumnType("text");
b.Property<int>("PracticeStage")
.HasColumnType("integer");
b.Property<bool>("PracticeVisualize")
.HasColumnType("boolean");
b.Property<string>("VerbParticiple")
.HasColumnType("text");
b.Property<string>("VerbPast")
.HasColumnType("text");
b.Property<string>("Word")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Vocabulary");
});
modelBuilder.Entity("Church.Net.Entity.WhoIsSpy", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Answer1Chs")
.HasColumnType("text");
b.Property<string>("Answer1Cht")
.HasColumnType("text");
b.Property<string>("Answer1En")
.HasColumnType("text");
b.Property<string>("Answer2Chs")
.HasColumnType("text");
b.Property<string>("Answer2Cht")
.HasColumnType("text");
b.Property<string>("Answer2En")
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("WhoIsSpy");
});
modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEventAttendee", b =>
{
b.HasOne("Church.Net.Entity.CellGroupRoutineEvent", "CellGroupRoutineEvent")
.WithMany("Attendees")
.HasForeignKey("EventId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("CellGroupRoutineEvent");
});
modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEventPrayer", b =>
{
b.HasOne("Church.Net.Entity.CellGroupRoutineEvent", "CellGroupRoutineEvent")
.WithMany("Prayers")
.HasForeignKey("EventId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("CellGroupRoutineEvent");
});
modelBuilder.Entity("Church.Net.Entity.FamilyMember", b =>
{
b.HasOne("Church.Net.Entity.Career", "Career")
.WithMany()
.HasForeignKey("CareerId");
b.Navigation("Career");
});
modelBuilder.Entity("Church.Net.Entity.FamilyMemberOAuth", b =>
{
b.HasOne("Church.Net.Entity.FamilyMember", null)
.WithMany("OAuthInfos")
.HasForeignKey("FamilyMemberId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Church.Net.Entity.HappinessBEST", b =>
{
b.HasOne("Church.Net.Entity.HappinessGroup", "HappinessGroup")
.WithMany("BestList")
.HasForeignKey("GroupId");
b.Navigation("HappinessGroup");
});
modelBuilder.Entity("Church.Net.Entity.HappinessTask", b =>
{
b.HasOne("Church.Net.Entity.HappinessWeek", "HappinessWeek")
.WithMany("Tasks")
.HasForeignKey("WeekId");
b.Navigation("HappinessWeek");
});
modelBuilder.Entity("Church.Net.Entity.HappinessWeek", b =>
{
b.HasOne("Church.Net.Entity.HappinessGroup", "HappinessGroup")
.WithMany("Weeks")
.HasForeignKey("GroupId");
b.Navigation("HappinessGroup");
});
modelBuilder.Entity("Church.Net.Entity.NewVisitor", b =>
{
b.HasOne("Church.Net.Entity.Religion", "Religion")
.WithMany()
.HasForeignKey("ReligionId");
b.Navigation("Religion");
});
modelBuilder.Entity("Church.Net.Entity.PastoralDomain", b =>
{
b.HasOne("Church.Net.Entity.FamilyMember", "Leader")
.WithMany()
.HasForeignKey("LeaderMemberId");
b.HasOne("Church.Net.Entity.AddressInfo", "ServiceAddress")
.WithMany()
.HasForeignKey("ServiceAddressId");
b.Navigation("Leader");
b.Navigation("ServiceAddress");
});
modelBuilder.Entity("Church.Net.Entity.PastoralDomainAutoReplys", b =>
{
b.HasOne("Church.Net.Entity.AutoReplyItem", "FamilyMember")
.WithMany("AutoReplyItemRelations")
.HasForeignKey("AutoReplyItemId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Church.Net.Entity.PastoralDomain", "PastoralDomain")
.WithMany("AutoReplyItemRelations")
.HasForeignKey("PastoralDomainCommunityAppId")
.HasPrincipalKey("CommunityAppId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("FamilyMember");
b.Navigation("PastoralDomain");
});
modelBuilder.Entity("Church.Net.Entity.PastoralDomainMembers", b =>
{
b.HasOne("Church.Net.Entity.FamilyMember", "FamilyMember")
.WithMany("PastoralDomains")
.HasForeignKey("FamilyMemberId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Church.Net.Entity.PastoralDomain", "PastoralDomain")
.WithMany("Members")
.HasForeignKey("PastoralDomainId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("FamilyMember");
b.Navigation("PastoralDomain");
});
modelBuilder.Entity("Church.Net.Entity.AutoReplyItem", b =>
{
b.Navigation("AutoReplyItemRelations");
});
modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEvent", b =>
{
b.Navigation("Attendees");
b.Navigation("Prayers");
});
modelBuilder.Entity("Church.Net.Entity.FamilyMember", b =>
{
b.Navigation("OAuthInfos");
b.Navigation("PastoralDomains");
});
modelBuilder.Entity("Church.Net.Entity.HappinessGroup", b =>
{
b.Navigation("BestList");
b.Navigation("Weeks");
});
modelBuilder.Entity("Church.Net.Entity.HappinessWeek", b =>
{
b.Navigation("Tasks");
});
modelBuilder.Entity("Church.Net.Entity.PastoralDomain", b =>
{
b.Navigation("AutoReplyItemRelations");
b.Navigation("Members");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,43 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Church.Net.DAL.EFCoreDBF.Migrations
{
public partial class AddLienClient : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "CommunityAppId",
table: "HappinessGroups",
type: "text",
nullable: true);
migrationBuilder.CreateTable(
name: "LineMessageClients",
columns: table => new
{
Id = table.Column<string>(type: "text", nullable: false),
ClientId = table.Column<string>(type: "text", nullable: true),
IsGroup = table.Column<bool>(type: "boolean", nullable: false),
IsManager = table.Column<bool>(type: "boolean", nullable: false),
Name = table.Column<string>(type: "text", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_LineMessageClients", x => x.Id);
});
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "LineMessageClients");
migrationBuilder.DropColumn(
name: "CommunityAppId",
table: "HappinessGroups");
}
}
}

View File

@ -0,0 +1,845 @@
// <auto-generated />
using System;
using Church.Net.DAL.EF;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace Church.Net.DAL.EFCoreDBF.Migrations
{
[DbContext(typeof(ChurchNetContext))]
[Migration("20220930060508_LineMessageAccount")]
partial class LineMessageAccount
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "6.0.8")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("Church.Net.Entity.AddressInfo", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Address")
.HasColumnType("text");
b.Property<string>("City")
.HasColumnType("text");
b.Property<string>("State")
.HasColumnType("text");
b.Property<string>("Zip")
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("AddressInfos");
});
modelBuilder.Entity("Church.Net.Entity.AutoReplyItem", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Command")
.HasColumnType("text");
b.Property<string>("Content")
.HasColumnType("text");
b.Property<string>("Description")
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("AutoReplyItems");
});
modelBuilder.Entity("Church.Net.Entity.Career", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Name")
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.HasKey("Id");
b.ToTable("Careers");
});
modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEvent", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Address")
.HasColumnType("text");
b.Property<DateTime>("Time")
.HasColumnType("timestamp with time zone");
b.HasKey("Id");
b.ToTable("CellGroupRoutineEvents");
});
modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEventAttendee", b =>
{
b.Property<string>("EventId")
.HasColumnType("text")
.HasColumnOrder(0);
b.Property<string>("Id")
.HasColumnType("text")
.HasColumnOrder(1);
b.Property<string>("Comment")
.HasColumnType("text");
b.Property<bool>("JoinPotluck")
.HasColumnType("boolean");
b.Property<string>("Name")
.HasColumnType("text");
b.Property<string>("PotluckItem")
.HasColumnType("text");
b.HasKey("EventId", "Id");
b.ToTable("CellGroupRoutineEventAttendees");
});
modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEventPrayer", b =>
{
b.Property<string>("EventId")
.HasColumnType("text")
.HasColumnOrder(0);
b.Property<string>("MemberId")
.HasColumnType("text")
.HasColumnOrder(1);
b.Property<string>("Comment")
.HasColumnType("text");
b.Property<string>("Prayer")
.HasColumnType("text");
b.HasKey("EventId", "MemberId");
b.ToTable("CellGroupRoutineEventPrayers");
});
modelBuilder.Entity("Church.Net.Entity.FamilyMember", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Address")
.HasMaxLength(500)
.HasColumnType("character varying(500)");
b.Property<string>("AvatarImage")
.HasColumnType("text");
b.Property<bool>("Baptized")
.HasColumnType("boolean");
b.Property<DateTime?>("Birthday")
.HasColumnType("timestamp with time zone");
b.Property<string>("CareerId")
.HasColumnType("text");
b.Property<string>("Comment")
.HasColumnType("text");
b.Property<string>("ComunityAppId")
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<DateTime?>("DateOfBaptized")
.HasColumnType("timestamp with time zone");
b.Property<DateTime?>("DateOfWalkIn")
.HasColumnType("timestamp with time zone");
b.Property<string>("Email")
.HasColumnType("text");
b.Property<string>("FirstName")
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<int>("Gender")
.HasColumnType("integer");
b.Property<string>("LastName")
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<bool>("Married")
.HasColumnType("boolean");
b.Property<string>("Password")
.HasColumnType("text");
b.Property<int>("Role")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("CareerId");
b.ToTable("FamilyMembers");
});
modelBuilder.Entity("Church.Net.Entity.FamilyMemberOAuth", b =>
{
b.Property<string>("FamilyMemberId")
.HasColumnType("text")
.HasColumnOrder(0);
b.Property<string>("OAuthType")
.HasColumnType("text")
.HasColumnOrder(1);
b.Property<string>("OAuthAccessToken")
.HasColumnType("text");
b.HasKey("FamilyMemberId", "OAuthType");
b.ToTable("FamilyMemberOAuths");
});
modelBuilder.Entity("Church.Net.Entity.HappinessBEST", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Email")
.HasColumnType("text");
b.Property<string>("GroupId")
.HasColumnType("text");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Phone")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("GroupId");
b.ToTable("HappinessBESTs");
});
modelBuilder.Entity("Church.Net.Entity.HappinessGroup", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Address")
.HasColumnType("text");
b.Property<DateTime>("BeginTime")
.HasColumnType("timestamp with time zone");
b.Property<string>("CityAndZipCode")
.HasColumnType("text");
b.Property<string>("CommunityAppId")
.HasColumnType("text");
b.Property<string>("InvitationText")
.HasColumnType("text");
b.Property<string>("Name")
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("HappinessGroups");
});
modelBuilder.Entity("Church.Net.Entity.HappinessTask", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Content")
.HasColumnType("text");
b.Property<string>("Tasker")
.HasColumnType("text");
b.Property<int>("Type")
.HasColumnType("integer");
b.Property<string>("WeekId")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("WeekId");
b.ToTable("HappinessTask");
});
modelBuilder.Entity("Church.Net.Entity.HappinessWeek", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Address")
.HasColumnType("text");
b.Property<string>("CityAndZipCode")
.HasColumnType("text");
b.Property<string>("Comment")
.HasColumnType("text");
b.Property<DateTime>("Date")
.HasColumnType("timestamp with time zone");
b.Property<string>("GroupId")
.HasColumnType("text");
b.Property<string>("InvitationText")
.HasColumnType("text");
b.Property<int>("SEQ")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("GroupId");
b.ToTable("HappinessWeeks");
});
modelBuilder.Entity("Church.Net.Entity.LineMessagingAccount", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("ChatToken")
.HasColumnType("text");
b.Property<string>("Name")
.HasColumnType("text");
b.Property<int>("Seq")
.HasColumnType("integer");
b.Property<int>("TotalUsage")
.HasColumnType("integer");
b.HasKey("Id");
b.ToTable("LineMessagingAccounts");
});
modelBuilder.Entity("Church.Net.Entity.LogInfo", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("DetailMessage")
.HasColumnType("text");
b.Property<int>("Level")
.HasColumnType("integer");
b.Property<string>("Message")
.HasColumnType("text");
b.Property<string>("Source")
.HasColumnType("text");
b.Property<string>("StackTrace")
.HasColumnType("text");
b.Property<DateTime>("Time")
.HasColumnType("timestamp with time zone");
b.Property<int>("TrackNo")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("TrackNo"));
b.Property<string>("Url")
.HasColumnType("text");
b.Property<string>("UserId")
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("LogInfos");
});
modelBuilder.Entity("Church.Net.Entity.Messenger.LineMessageClient", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("ClientId")
.HasColumnType("text");
b.Property<bool>("IsGroup")
.HasColumnType("boolean");
b.Property<bool>("IsManager")
.HasColumnType("boolean");
b.Property<string>("Name")
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("LineMessageClients");
});
modelBuilder.Entity("Church.Net.Entity.NewVisitor", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Address")
.HasMaxLength(500)
.HasColumnType("character varying(500)");
b.Property<DateTime?>("BirthDate")
.HasColumnType("timestamp with time zone");
b.Property<string>("ComunityAppId")
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<string>("Email")
.HasMaxLength(150)
.HasColumnType("character varying(150)");
b.Property<string>("FirstName")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<int>("Gender")
.HasColumnType("integer");
b.Property<string>("LastName")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<string>("Note")
.HasColumnType("text");
b.Property<string>("Phone")
.IsRequired()
.HasMaxLength(150)
.HasColumnType("character varying(150)");
b.Property<int?>("ReligionId")
.HasColumnType("integer");
b.Property<DateTime>("VisitingDate")
.HasColumnType("timestamp with time zone");
b.HasKey("Id");
b.HasIndex("ReligionId");
b.ToTable("NewVisitors");
});
modelBuilder.Entity("Church.Net.Entity.PastoralDomain", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("CommunityAppId")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Description")
.HasColumnType("text");
b.Property<string>("Image1")
.HasColumnType("text");
b.Property<string>("Image2")
.HasColumnType("text");
b.Property<string>("Image3")
.HasColumnType("text");
b.Property<string>("Image4")
.HasColumnType("text");
b.Property<string>("Image5")
.HasColumnType("text");
b.Property<string>("LeaderMemberId")
.HasColumnType("text");
b.Property<string>("LogoImage")
.HasColumnType("text");
b.Property<string>("Name")
.HasColumnType("text");
b.Property<string>("ServiceAddressId")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("LeaderMemberId");
b.HasIndex("ServiceAddressId");
b.ToTable("PastoralDomains");
});
modelBuilder.Entity("Church.Net.Entity.PastoralDomainAutoReplys", b =>
{
b.Property<string>("PastoralDomainCommunityAppId")
.HasColumnType("text")
.HasColumnOrder(0);
b.Property<string>("AutoReplyItemId")
.HasColumnType("text")
.HasColumnOrder(1);
b.HasKey("PastoralDomainCommunityAppId", "AutoReplyItemId");
b.HasIndex("AutoReplyItemId");
b.ToTable("PastoralDomainAutoReplys");
});
modelBuilder.Entity("Church.Net.Entity.PastoralDomainMembers", b =>
{
b.Property<string>("PastoralDomainId")
.HasColumnType("text")
.HasColumnOrder(0);
b.Property<string>("FamilyMemberId")
.HasColumnType("text")
.HasColumnOrder(1);
b.HasKey("PastoralDomainId", "FamilyMemberId");
b.HasIndex("FamilyMemberId");
b.ToTable("PastoralDomainMembers");
});
modelBuilder.Entity("Church.Net.Entity.Religion", b =>
{
b.Property<int>("ReligionId")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("ReligionId"));
b.Property<string>("Name")
.HasColumnType("text");
b.HasKey("ReligionId");
b.ToTable("Religions");
});
modelBuilder.Entity("Church.Net.Entity.Vocabulary", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("DefinitionCh")
.IsRequired()
.HasColumnType("text");
b.Property<string>("DefinitionEn")
.IsRequired()
.HasColumnType("text");
b.Property<int>("FlashCardTimes")
.HasColumnType("integer");
b.Property<string>("ImagesUrl")
.HasColumnType("text");
b.Property<DateTime>("InsertDate")
.HasColumnType("timestamp with time zone");
b.Property<string>("NounPlural")
.HasColumnType("text");
b.Property<int>("PartOfSpeech")
.HasColumnType("integer");
b.Property<bool>("PracticeApply")
.HasColumnType("boolean");
b.Property<DateTime>("PracticeDate")
.HasColumnType("timestamp with time zone");
b.Property<bool>("PracticeMemorized")
.HasColumnType("boolean");
b.Property<bool>("PracticeReview")
.HasColumnType("boolean");
b.Property<bool>("PracticeSelect")
.HasColumnType("boolean");
b.Property<string>("PracticeSentence")
.HasColumnType("text");
b.Property<int>("PracticeStage")
.HasColumnType("integer");
b.Property<bool>("PracticeVisualize")
.HasColumnType("boolean");
b.Property<string>("VerbParticiple")
.HasColumnType("text");
b.Property<string>("VerbPast")
.HasColumnType("text");
b.Property<string>("Word")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Vocabulary");
});
modelBuilder.Entity("Church.Net.Entity.WhoIsSpy", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Answer1Chs")
.HasColumnType("text");
b.Property<string>("Answer1Cht")
.HasColumnType("text");
b.Property<string>("Answer1En")
.HasColumnType("text");
b.Property<string>("Answer2Chs")
.HasColumnType("text");
b.Property<string>("Answer2Cht")
.HasColumnType("text");
b.Property<string>("Answer2En")
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("WhoIsSpy");
});
modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEventAttendee", b =>
{
b.HasOne("Church.Net.Entity.CellGroupRoutineEvent", "CellGroupRoutineEvent")
.WithMany("Attendees")
.HasForeignKey("EventId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("CellGroupRoutineEvent");
});
modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEventPrayer", b =>
{
b.HasOne("Church.Net.Entity.CellGroupRoutineEvent", "CellGroupRoutineEvent")
.WithMany("Prayers")
.HasForeignKey("EventId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("CellGroupRoutineEvent");
});
modelBuilder.Entity("Church.Net.Entity.FamilyMember", b =>
{
b.HasOne("Church.Net.Entity.Career", "Career")
.WithMany()
.HasForeignKey("CareerId");
b.Navigation("Career");
});
modelBuilder.Entity("Church.Net.Entity.FamilyMemberOAuth", b =>
{
b.HasOne("Church.Net.Entity.FamilyMember", null)
.WithMany("OAuthInfos")
.HasForeignKey("FamilyMemberId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Church.Net.Entity.HappinessBEST", b =>
{
b.HasOne("Church.Net.Entity.HappinessGroup", "HappinessGroup")
.WithMany("BestList")
.HasForeignKey("GroupId");
b.Navigation("HappinessGroup");
});
modelBuilder.Entity("Church.Net.Entity.HappinessTask", b =>
{
b.HasOne("Church.Net.Entity.HappinessWeek", "HappinessWeek")
.WithMany("Tasks")
.HasForeignKey("WeekId");
b.Navigation("HappinessWeek");
});
modelBuilder.Entity("Church.Net.Entity.HappinessWeek", b =>
{
b.HasOne("Church.Net.Entity.HappinessGroup", "HappinessGroup")
.WithMany("Weeks")
.HasForeignKey("GroupId");
b.Navigation("HappinessGroup");
});
modelBuilder.Entity("Church.Net.Entity.NewVisitor", b =>
{
b.HasOne("Church.Net.Entity.Religion", "Religion")
.WithMany()
.HasForeignKey("ReligionId");
b.Navigation("Religion");
});
modelBuilder.Entity("Church.Net.Entity.PastoralDomain", b =>
{
b.HasOne("Church.Net.Entity.FamilyMember", "Leader")
.WithMany()
.HasForeignKey("LeaderMemberId");
b.HasOne("Church.Net.Entity.AddressInfo", "ServiceAddress")
.WithMany()
.HasForeignKey("ServiceAddressId");
b.Navigation("Leader");
b.Navigation("ServiceAddress");
});
modelBuilder.Entity("Church.Net.Entity.PastoralDomainAutoReplys", b =>
{
b.HasOne("Church.Net.Entity.AutoReplyItem", "FamilyMember")
.WithMany("AutoReplyItemRelations")
.HasForeignKey("AutoReplyItemId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Church.Net.Entity.PastoralDomain", "PastoralDomain")
.WithMany("AutoReplyItemRelations")
.HasForeignKey("PastoralDomainCommunityAppId")
.HasPrincipalKey("CommunityAppId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("FamilyMember");
b.Navigation("PastoralDomain");
});
modelBuilder.Entity("Church.Net.Entity.PastoralDomainMembers", b =>
{
b.HasOne("Church.Net.Entity.FamilyMember", "FamilyMember")
.WithMany("PastoralDomains")
.HasForeignKey("FamilyMemberId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Church.Net.Entity.PastoralDomain", "PastoralDomain")
.WithMany("Members")
.HasForeignKey("PastoralDomainId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("FamilyMember");
b.Navigation("PastoralDomain");
});
modelBuilder.Entity("Church.Net.Entity.AutoReplyItem", b =>
{
b.Navigation("AutoReplyItemRelations");
});
modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEvent", b =>
{
b.Navigation("Attendees");
b.Navigation("Prayers");
});
modelBuilder.Entity("Church.Net.Entity.FamilyMember", b =>
{
b.Navigation("OAuthInfos");
b.Navigation("PastoralDomains");
});
modelBuilder.Entity("Church.Net.Entity.HappinessGroup", b =>
{
b.Navigation("BestList");
b.Navigation("Weeks");
});
modelBuilder.Entity("Church.Net.Entity.HappinessWeek", b =>
{
b.Navigation("Tasks");
});
modelBuilder.Entity("Church.Net.Entity.PastoralDomain", b =>
{
b.Navigation("AutoReplyItemRelations");
b.Navigation("Members");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,33 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Church.Net.DAL.EFCoreDBF.Migrations
{
public partial class LineMessageAccount : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "LineMessagingAccounts",
columns: table => new
{
Id = table.Column<string>(type: "text", nullable: false),
Name = table.Column<string>(type: "text", nullable: true),
ChatToken = table.Column<string>(type: "text", nullable: true),
TotalUsage = table.Column<int>(type: "integer", nullable: false),
Seq = table.Column<int>(type: "integer", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_LineMessagingAccounts", x => x.Id);
});
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "LineMessagingAccounts");
}
}
}

View File

@ -262,6 +262,9 @@ namespace Church.Net.DAL.EFCoreDBF.Migrations
b.Property<string>("CityAndZipCode") b.Property<string>("CityAndZipCode")
.HasColumnType("text"); .HasColumnType("text");
b.Property<string>("CommunityAppId")
.HasColumnType("text");
b.Property<string>("InvitationText") b.Property<string>("InvitationText")
.HasColumnType("text"); .HasColumnType("text");
@ -273,6 +276,30 @@ namespace Church.Net.DAL.EFCoreDBF.Migrations
b.ToTable("HappinessGroups"); b.ToTable("HappinessGroups");
}); });
modelBuilder.Entity("Church.Net.Entity.HappinessTask", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Content")
.HasColumnType("text");
b.Property<string>("Tasker")
.HasColumnType("text");
b.Property<int>("Type")
.HasColumnType("integer");
b.Property<string>("WeekId")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("WeekId");
b.ToTable("HappinessTask");
});
modelBuilder.Entity("Church.Net.Entity.HappinessWeek", b => modelBuilder.Entity("Church.Net.Entity.HappinessWeek", b =>
{ {
b.Property<string>("Id") b.Property<string>("Id")
@ -284,6 +311,9 @@ namespace Church.Net.DAL.EFCoreDBF.Migrations
b.Property<string>("CityAndZipCode") b.Property<string>("CityAndZipCode")
.HasColumnType("text"); .HasColumnType("text");
b.Property<string>("Comment")
.HasColumnType("text");
b.Property<DateTime>("Date") b.Property<DateTime>("Date")
.HasColumnType("timestamp with time zone"); .HasColumnType("timestamp with time zone");
@ -303,6 +333,28 @@ namespace Church.Net.DAL.EFCoreDBF.Migrations
b.ToTable("HappinessWeeks"); b.ToTable("HappinessWeeks");
}); });
modelBuilder.Entity("Church.Net.Entity.LineMessagingAccount", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("ChatToken")
.HasColumnType("text");
b.Property<string>("Name")
.HasColumnType("text");
b.Property<int>("Seq")
.HasColumnType("integer");
b.Property<int>("TotalUsage")
.HasColumnType("integer");
b.HasKey("Id");
b.ToTable("LineMessagingAccounts");
});
modelBuilder.Entity("Church.Net.Entity.LogInfo", b => modelBuilder.Entity("Church.Net.Entity.LogInfo", b =>
{ {
b.Property<string>("Id") b.Property<string>("Id")
@ -343,6 +395,28 @@ namespace Church.Net.DAL.EFCoreDBF.Migrations
b.ToTable("LogInfos"); b.ToTable("LogInfos");
}); });
modelBuilder.Entity("Church.Net.Entity.Messenger.LineMessageClient", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("ClientId")
.HasColumnType("text");
b.Property<bool>("IsGroup")
.HasColumnType("boolean");
b.Property<bool>("IsManager")
.HasColumnType("boolean");
b.Property<string>("Name")
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("LineMessageClients");
});
modelBuilder.Entity("Church.Net.Entity.NewVisitor", b => modelBuilder.Entity("Church.Net.Entity.NewVisitor", b =>
{ {
b.Property<string>("Id") b.Property<string>("Id")
@ -645,6 +719,15 @@ namespace Church.Net.DAL.EFCoreDBF.Migrations
b.Navigation("HappinessGroup"); b.Navigation("HappinessGroup");
}); });
modelBuilder.Entity("Church.Net.Entity.HappinessTask", b =>
{
b.HasOne("Church.Net.Entity.HappinessWeek", "HappinessWeek")
.WithMany("Tasks")
.HasForeignKey("WeekId");
b.Navigation("HappinessWeek");
});
modelBuilder.Entity("Church.Net.Entity.HappinessWeek", b => modelBuilder.Entity("Church.Net.Entity.HappinessWeek", b =>
{ {
b.HasOne("Church.Net.Entity.HappinessGroup", "HappinessGroup") b.HasOne("Church.Net.Entity.HappinessGroup", "HappinessGroup")
@ -743,6 +826,11 @@ namespace Church.Net.DAL.EFCoreDBF.Migrations
b.Navigation("Weeks"); b.Navigation("Weeks");
}); });
modelBuilder.Entity("Church.Net.Entity.HappinessWeek", b =>
{
b.Navigation("Tasks");
});
modelBuilder.Entity("Church.Net.Entity.PastoralDomain", b => modelBuilder.Entity("Church.Net.Entity.PastoralDomain", b =>
{ {
b.Navigation("AutoReplyItemRelations"); b.Navigation("AutoReplyItemRelations");

View File

@ -19,6 +19,11 @@ namespace Church.Net.Entity
public string Address { get; set; } public string Address { get; set; }
public virtual ICollection<CellGroupRoutineEventAttendee> Attendees { get; set; } public virtual ICollection<CellGroupRoutineEventAttendee> Attendees { get; set; }
public virtual ICollection<CellGroupRoutineEventPrayer> Prayers { get; set; } public virtual ICollection<CellGroupRoutineEventPrayer> Prayers { get; set; }
[ForeignKey("CellGroupInfo")]
public string PastoralDomainId { get; set; }
public PastoralDomain CellGroupInfo { get; set; }
} }
public class CellGroupRoutineEventAttendee : ICombinedKeyEntity public class CellGroupRoutineEventAttendee : ICombinedKeyEntity
{ {

View File

@ -9,7 +9,7 @@ using System.Threading.Tasks;
namespace Church.Net.Entity namespace Church.Net.Entity
{ {
public class HappinessGroup : IEntity public class HappinessGroup : IEntity, IMessengerClient
{ {
[Required, Key] [Required, Key]
public string Id { get; set; } public string Id { get; set; }
@ -25,5 +25,11 @@ namespace Church.Net.Entity
public virtual ICollection<HappinessBEST> BestList { get; set; } public virtual ICollection<HappinessBEST> BestList { get; set; }
public virtual ICollection<HappinessWeek> Weeks { get; set; } public virtual ICollection<HappinessWeek> Weeks { get; set; }
public string CommunityAppId { get; set; }
[ForeignKey("LineMessagingAccount")]
public string LineAccountId { get; set; }
public virtual LineMessagingAccount LineMessagingAccount { get; set; }
} }
} }

View File

@ -25,5 +25,28 @@ namespace Church.Net.Entity
public int SEQ { get; set; } public int SEQ { get; set; }
[NotMapped] [NotMapped]
public bool UpdateRestWeekDate { get; set; } public bool UpdateRestWeekDate { get; set; }
public virtual ICollection<HappinessTask> Tasks { get; set; }
public string Comment { get; set; }
}
public enum HappinessTaskType
{
IceBreak,
Worship,
Testimony,
Message,
Gift,
Dessert
}
public class HappinessTask : IEntity
{
[ForeignKey("HappinessWeek")]
public string WeekId { get; set; }
public HappinessWeek HappinessWeek { get; set; }
[Required, Key]
public string Id { get; set; }
public HappinessTaskType Type { get; set; }
public string Tasker { get; set; }
public string Content { get; set; }
} }
} }

View File

@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
namespace Church.Net.Entity.Interface
{
public enum MessengerType
{
Email,
Line,
Wechat,
SMS
}
public interface IMessenger
{
MessengerType Type { get; }
Task<bool> SendMessage(IMessengerClient target, string message);
Task<bool> SendMessage(IMessengerClient target, object message);
}
public interface IMessengerClient
{
string Id { get; }
string LineAccountId { get; set; }
LineMessagingAccount LineMessagingAccount { get; set; }
}
public interface IMessageClient: IEntity
{
MessengerType Type { get; }
string ClientId { get; set; }
}
}

View File

@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Text;
namespace Church.Net.Entity
{
public class LineBotInfo
{
public string Id { get; set; }
public string GroupId { get; set; }
}
public class LineClient
{
[Required, Key]
public string Id { get; set; }
public string LineId { get; set; }
public bool IsGroup { get; set; }
public bool IsManager { get; set; }
public string Name { get; set; }
}
}

View File

@ -0,0 +1,16 @@
using Church.Net.Entity.Interface;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace Church.Net.Entity
{
public class LineMessagingAccount : IEntity
{
[Required, Key]
public string Id { get; set; }
public string Name { get; set; }
public string ChatToken { get; set; }
public int TotalUsage { get; set; }
public int Seq { get; set; }
}
}

View File

@ -0,0 +1,20 @@
using Church.Net.Entity.Interface;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Text;
namespace Church.Net.Entity.Messenger
{
public class LineMessageClient : IMessageClient
{
public MessengerType Type => MessengerType.Line;
[Required, Key]
public string Id { get; set; }
public string ClientId { get; set; }
public bool IsGroup { get; set; }
public bool IsManager { get; set; }
public string Name { get; set; }
}
}

View File

@ -10,7 +10,7 @@ using System.Threading.Tasks;
namespace Church.Net.Entity namespace Church.Net.Entity
{ {
public class PastoralDomain : IEntity public class PastoralDomain : IEntity, IMessengerClient
{ {
public PastoralDomain() public PastoralDomain()
{ {
@ -31,8 +31,12 @@ namespace Church.Net.Entity
public string Image4 { get; set; } public string Image4 { get; set; }
public string Image5 { get; set; } public string Image5 { get; set; }
public string CommunityAppId { get; set; } public string CommunityAppId { get; set; }
[ForeignKey("LineMessagingAccount")]
public string LineAccountId { get; set; }
public virtual LineMessagingAccount LineMessagingAccount { get; set; }
[ForeignKey("Leader")] [ForeignKey("Leader")]
public string LeaderMemberId { get; set; } public string LeaderMemberId { get; set; }

View File

@ -5,6 +5,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="SixLabors.ImageSharp" Version="2.1.3" />
<PackageReference Include="System.Drawing.Common" Version="5.0.2" /> <PackageReference Include="System.Drawing.Common" Version="5.0.2" />
</ItemGroup> </ItemGroup>

View File

@ -9,7 +9,7 @@ namespace Church.Net.Utility
public static class DateTimeHelper public static class DateTimeHelper
{ {
private static TimeZoneInfo pacificZone = TimeZoneInfo.FindSystemTimeZoneById("Pacific SA Standard Time"); private static TimeZoneInfo pacificZone = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time");
public static DateTime GetNextWeekday(DateTime start, DayOfWeek day) public static DateTime GetNextWeekday(DateTime start, DayOfWeek day)
{ {
// The (... + 7) % 7 ensures we end up with a value in the range [0, 6] // The (... + 7) % 7 ensures we end up with a value in the range [0, 6]
@ -18,11 +18,11 @@ namespace Church.Net.Utility
} }
public static DateTime Now() public static DateTime Now()
{ {
return DateTime.SpecifyKind(TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, pacificZone),DateTimeKind.Local); return TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, pacificZone);
} }
public static DateTime Today() public static DateTime Today()
{ {
return TimeZoneInfo.ConvertTimeFromUtc(DateTime.Today, pacificZone); return Now().Date;
} }
} }
} }

View File

@ -1,4 +1,5 @@
using System; using SixLabors.ImageSharp.Processing;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.Drawing.Drawing2D; using System.Drawing.Drawing2D;
@ -248,7 +249,7 @@ namespace Church.Net.Utility
} }
public static class Image public static class ImageHelper
{ {
public static Bitmap CreateThumbnail(string lcFilename, int lnWidth, int lnHeight) public static Bitmap CreateThumbnail(string lcFilename, int lnWidth, int lnHeight)
{ {
@ -369,6 +370,14 @@ namespace Church.Net.Utility
return bmp.Resize(bmp.Width * percentage / 100, bmp.Height * percentage / 100); return bmp.Resize(bmp.Width * percentage / 100, bmp.Height * percentage / 100);
} }
public static void Scalling(this SixLabors.ImageSharp.Image image, int percentage)
{
var scale = (double)percentage/100;
var scaleWidth = (int)(image.Width * scale);
var scaleHeight = (int)(image.Height * scale);
image.Mutate(o => o.Resize(new SixLabors.ImageSharp.Size(scaleWidth, scaleHeight)));
}
public static Bitmap Superimpose(Bitmap largeBmp, Bitmap smallBmp, int? x = null, int? y = null) public static Bitmap Superimpose(Bitmap largeBmp, Bitmap smallBmp, int? x = null, int? y = null)

View File

@ -0,0 +1,27 @@
using System;
using System.Threading.Tasks;
namespace LineMessaging
{
public partial class LineMessagingClient
{
private const string GroupProfileApiPath = "v2/bot/group/{0}/summary";
private const string QuotaApiPath = "/v2/bot/message/quota/consumption";
public async Task<int> GetTotalUsage()
{
return Get<LineUsage>(QuotaApiPath).Result.TotalUsage;
}
public async Task<LineGroupProfile> GetGroupProfile(string groupId)
{
if (string.IsNullOrEmpty(groupId))
{
throw new ArgumentException($"{nameof(groupId)} is null or empty.");
}
return await Get<LineGroupProfile>(string.Format(GroupProfileApiPath, groupId));
}
}
}

View File

@ -0,0 +1,16 @@
using Newtonsoft.Json;
namespace LineMessaging
{
public class LineUsage
{
[JsonProperty("totalUsage")]
public int TotalUsage { get; set; }
}
public class LineGroupProfile
{
[JsonProperty("groupName")]
public string GroupName { get; set; }
}
}

View File

@ -11,6 +11,7 @@ namespace LineMessaging
public partial class LineMessagingClient public partial class LineMessagingClient
{ {
private const string ACCESS_TOKEN = "WFAyMvMEZ86cfMJIAzE+yklUZGpeS/jFYTeL9a9O35QR83oNMmwaUJfyEe48Kegadz0BArDdBoySxs479U1pwTHtlyH+Sm4jqlz8BwukX/Hsa4D1fX03Qn4zFu7TwPFKWFXnZbWq89Yg0iNzjpfTNwdB04t89/1O/w1cDnyilFU="; private const string ACCESS_TOKEN = "WFAyMvMEZ86cfMJIAzE+yklUZGpeS/jFYTeL9a9O35QR83oNMmwaUJfyEe48Kegadz0BArDdBoySxs479U1pwTHtlyH+Sm4jqlz8BwukX/Hsa4D1fX03Qn4zFu7TwPFKWFXnZbWq89Yg0iNzjpfTNwdB04t89/1O/w1cDnyilFU=";
private const string ACCESS_TOKEN_SEC = "UTRu3QsV9BjVmusqgWa30j/Vs7JJb59NvIWprv9Yb4ORUOTIIco66groSy7n8TlQbxn/OsA6FsFSQZDwaRPPlyfBYoW+lvv8g7IZhA8otuK57f+ojZbLO0RvkyEyQoy09Kmd7dnr78kHlDOcBq5ATgdB04t89/1O/w1cDnyilFU=";
private static readonly MediaTypeHeaderValue MediaTypeJson = MediaTypeHeaderValue.Parse("application/json; charset=utf-8"); private static readonly MediaTypeHeaderValue MediaTypeJson = MediaTypeHeaderValue.Parse("application/json; charset=utf-8");
private static readonly MediaTypeHeaderValue MediaTypeJpeg = MediaTypeHeaderValue.Parse("image/jpeg"); private static readonly MediaTypeHeaderValue MediaTypeJpeg = MediaTypeHeaderValue.Parse("image/jpeg");
private static readonly MediaTypeHeaderValue MediaTypePng = MediaTypeHeaderValue.Parse("image/png"); private static readonly MediaTypeHeaderValue MediaTypePng = MediaTypeHeaderValue.Parse("image/png");
@ -25,11 +26,21 @@ namespace LineMessaging
Timeout = TimeSpan.FromSeconds(10) Timeout = TimeSpan.FromSeconds(10)
}; };
private readonly AuthenticationHeaderValue accessTokenHeaderValue; private AuthenticationHeaderValue accessTokenHeaderValue;
private JsonSerializerSettings serializerSettings; private JsonSerializerSettings serializerSettings;
public LineMessagingClient() public LineMessagingClient()
{ {
string accessToken = ACCESS_TOKEN; string accessToken = ACCESS_TOKEN_SEC;//ACCESS_TOKEN;
Initialize(accessToken);
}
public LineMessagingClient(string accessToken)
{
Initialize(accessToken);
}
private void Initialize(string accessToken)
{
if (string.IsNullOrEmpty(accessToken)) if (string.IsNullOrEmpty(accessToken))
{ {
throw new ArgumentException($"{nameof(accessToken)} is null or empty."); throw new ArgumentException($"{nameof(accessToken)} is null or empty.");
@ -38,7 +49,7 @@ namespace LineMessaging
{ {
ContractResolver = new CamelCasePropertyNamesContractResolver(), ContractResolver = new CamelCasePropertyNamesContractResolver(),
NullValueHandling = NullValueHandling.Ignore, NullValueHandling = NullValueHandling.Ignore,
Formatting=Formatting.Indented Formatting = Formatting.Indented
}; };
accessTokenHeaderValue = new AuthenticationHeaderValue("Bearer", accessToken); accessTokenHeaderValue = new AuthenticationHeaderValue("Bearer", accessToken);
} }

BIN
WebAPI/App_Data/arial.ttf Normal file

Binary file not shown.

View File

@ -1,5 +1,6 @@
using Church.Net.Entity; using Church.Net.Entity;
using Church.Net.Entity.Interface; using Church.Net.Entity.Interface;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -7,6 +8,7 @@ using WebAPI.Logics.Interface;
namespace WebAPI.Controllers namespace WebAPI.Controllers
{ {
[Authorize]
public class ApiControllerBase<T> : ControllerBase where T : IEntity public class ApiControllerBase<T> : ControllerBase where T : IEntity
{ {
protected readonly ICrudLogic<T> logic; protected readonly ICrudLogic<T> logic;
@ -74,6 +76,7 @@ namespace WebAPI.Controllers
} }
} }
[Authorize]
public class CombinedKeyApiControllerBase<T> : ControllerBase where T : ICombinedKeyEntity public class CombinedKeyApiControllerBase<T> : ControllerBase where T : ICombinedKeyEntity
{ {
protected readonly ICombinedKeyCrudLogic<T> logic; protected readonly ICombinedKeyCrudLogic<T> logic;

View File

@ -1,20 +1,18 @@
using System; using System.Collections.Generic;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging; using System.Drawing.Imaging;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Net; using System.Runtime.InteropServices;
using System.Net.Http;
using System.Threading.Tasks; using System.Threading.Tasks;
using Church.Net.DAL.EF;
using Church.Net.Entity; using Church.Net.Entity;
using Church.Net.Utility; using Church.Net.Utility;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Primitives;
using QRCoder; using QRCoder;
using SixLabors.Fonts;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Drawing.Processing;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Processing;
using WebAPI.Logics.Interface; using WebAPI.Logics.Interface;
// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860 // For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
@ -61,13 +59,15 @@ namespace WebAPI.Controllers
public async Task<IActionResult> GetInvitationQRcode(string id) public async Task<IActionResult> GetInvitationQRcode(string id)
{ {
QRCodeGenerator gen = new QRCodeGenerator();
QRCodeGenerator qrGenerator = new QRCodeGenerator(); QRCodeGenerator qrGenerator = new QRCodeGenerator();
QRCodeData qrCodeData = qrGenerator.CreateQrCode($"http://happiness.tours/invitation/{id}", QRCodeGenerator.ECCLevel.Q); QRCodeData qrCodeData = qrGenerator.CreateQrCode($"https://happiness.tours/invitation/{id}", QRCodeGenerator.ECCLevel.Q);
QRCode qrCode = new QRCode(qrCodeData); QRCode qrCode = new QRCode(qrCodeData);
Bitmap qrCodeImage = qrCode.GetGraphic(3); var qrCodeImage = qrCode.GetGraphic(3);
string qrCodeImagePath = ServerUtils.MapPath("App_Data/ScaneMeQrCode.png"); string qrCodeImagePath = "/App_Data/ScaneMeQrCode.png";
var backgroundBitmap = (Bitmap)Bitmap.FromFile(qrCodeImagePath);
var backgroundBitmap = SixLabors.ImageSharp.Image.Load(qrCodeImagePath);
//string qrCodeImagePath = Environment.GetEnvironmentVariable("AppData"); //string qrCodeImagePath = Environment.GetEnvironmentVariable("AppData");
//HttpContext.Current.Server.MapPath("~/App_Data/"); //HttpContext.Current.Server.MapPath("~/App_Data/");
//var fullPath = System.Web.Hosting.HostingEnvironment.MapPath(@"~/App_Data/ScaneMeQrCode.png"); //var fullPath = System.Web.Hosting.HostingEnvironment.MapPath(@"~/App_Data/ScaneMeQrCode.png");
@ -81,9 +81,9 @@ namespace WebAPI.Controllers
using (var memoryStream = new MemoryStream()) using (var memoryStream = new MemoryStream())
{ {
//fileStream.CopyTo(memoryStream); //fileStream.CopyTo(memoryStream);
Bitmap image = Superimpose(best.Name, backgroundBitmap, qrCodeImage, 10, 32); var image = Superimpose(best.Name, backgroundBitmap, qrCodeImage, 10, 32);
image.Scalling(75).Save(memoryStream, ImageFormat.Png); image.Scalling(75);
image.SaveAsPng(memoryStream);
byte[] byteImage = memoryStream.ToArray(); byte[] byteImage = memoryStream.ToArray();
return File(byteImage, "image/png"); return File(byteImage, "image/png");
} }
@ -91,12 +91,16 @@ namespace WebAPI.Controllers
return this.NotFound(); return this.NotFound();
} }
private Font arialFont;
[NonAction] [NonAction]
public Bitmap Superimpose(string bestName, Bitmap largeBmp, Bitmap smallBmp, int? x = null, int? y = null) public Image Superimpose(string bestName, Image largeBmp, Image smallBmp, int? x = null, int? y = null)
{ {
Graphics g = Graphics.FromImage(largeBmp); FontCollection collection = new();
g.CompositingMode = CompositingMode.SourceOver; FontFamily family = collection.Add("/App_Data/arial.ttf");
smallBmp.MakeTransparent(); arialFont = family.CreateFont(12, FontStyle.Italic);
//Graphics g = Graphics.FromImage(largeBmp);
//g.CompositingMode = CompositingMode.SourceOver;
//smallBmp.MakeTransparent();
int margin = 5; int margin = 5;
if (!x.HasValue) if (!x.HasValue)
{ {
@ -109,9 +113,13 @@ namespace WebAPI.Controllers
var scale = 0.8; var scale = 0.8;
var scaleWidth = (int)(smallBmp.Width * scale); var scaleWidth = (int)(smallBmp.Width * scale);
var scaleHeight = (int)(smallBmp.Height * scale); var scaleHeight = (int)(smallBmp.Height * scale);
g.DrawImage(smallBmp, new Rectangle(x.Value, y.Value, scaleWidth, scaleHeight));
g.DrawString(bestName, new Font(new FontFamily("Arial"), 12), new SolidBrush(System.Drawing.Color.Black), 10, 0);
largeBmp.Mutate(x => x.DrawText(bestName, arialFont, Color.Black, new PointF(10, 10)));
smallBmp.Scalling(80);
largeBmp.Mutate(ctx => ctx.DrawImage(smallBmp, new Point(x.Value, y.Value),1f));
return largeBmp; return largeBmp;
} }

View File

@ -31,17 +31,15 @@ namespace WebAPI.Controllers
[Route("[controller]/[action]")] [Route("[controller]/[action]")]
public class LineMessageController : ControllerBase public class LineMessageController : ControllerBase
{ {
private readonly ChurchNetContext dbContext;
private readonly LineAutoBotService lineAutoBotService; private readonly LineAutoBotService lineAutoBotService;
private readonly ILoggingService loggingService; private readonly ILoggingService loggingService;
public LineMessageController(ChurchNetContext dbContext, public LineMessageController(
LineAutoBotService lineAutoBotService, LineAutoBotService lineAutoBotService,
ILoggingService loggingService ILoggingService loggingService
) )
{ {
this.dbContext = dbContext;
this.lineAutoBotService = lineAutoBotService; this.lineAutoBotService = lineAutoBotService;
this.loggingService = loggingService; this.loggingService = loggingService;
} }
@ -67,7 +65,9 @@ namespace WebAPI.Controllers
// POST api/<BestController> // POST api/<BestController>
[HttpPost] [HttpPost]
public async Task PostFromLine([FromBody] object jsonData) //[Route("[controller]/[action]")]
//[Route("[controller]/[action]/{id?}")]
public async Task PostFromLine(string id, [FromBody] object jsonData)
{ {
//string txtPath = ServerUtils.MapPath("App_Data/LinePostRawLog.txt"); //string txtPath = ServerUtils.MapPath("App_Data/LinePostRawLog.txt");
@ -76,7 +76,9 @@ namespace WebAPI.Controllers
{ {
LineWebhookContent content = JsonConvert.DeserializeObject<LineWebhookContent>(jsonData.ToString()); LineWebhookContent content = JsonConvert.DeserializeObject<LineWebhookContent>(jsonData.ToString());
await lineAutoBotService.AutoReply(content);
//this.loggingService.Log("PostFromLine");
await lineAutoBotService.AutoReply(content);
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -103,14 +105,15 @@ namespace WebAPI.Controllers
} }
[HttpGet] [HttpGet]
public Task PushCommandMessage(string groupToken,string command) public Task PushCommandMessage(string groupToken, string command)
{ {
return lineAutoBotService.PushCommandMessage(EnumHelper.GetEnumValueFromDescription<LineGroup>(groupToken), "#"+ command); return lineAutoBotService.PushCommandMessage(EnumHelper.GetEnumValueFromDescription<LineGroup>(groupToken), "#" + command);
} }
} }
public class LineMessage{ public class LineMessage
{
public string To { get; set; } public string To { get; set; }
public string Message { get; set; } public string Message { get; set; }
} }

View File

@ -0,0 +1,35 @@
using Church.Net.Entity;
using LineMessaging;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Threading.Tasks;
using WebAPI.Logics;
using WebAPI.Logics.Interface;
namespace WebAPI.Controllers
{
[Route("[controller]/[action]")]
[ApiController]
public class LineMessagingAccountController : ApiControllerBase<LineMessagingAccount>
{
public LineMessagingAccountController(LineMessagingAccountLogic logic) : base(logic)
{
}
[HttpGet]
public void RefreshAllQuota()
{
foreach (var item in logic.GetAll())
{
if (!string.IsNullOrWhiteSpace(item.ChatToken))
{
var lineMessegeClient = new LineMessagingClient(item.ChatToken);
item.TotalUsage = lineMessegeClient.GetTotalUsage().Result;
logic.Update(item);
}
}
}
}
}

View File

@ -1,10 +1,13 @@
using Church.Net.Entity; using Church.Net.Entity;
using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Hosting;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using WebAPI.Logics.Interface; using WebAPI.Logics.Interface;
using WebAPI.Services.Interfaces;
namespace WebAPI.Controllers namespace WebAPI.Controllers
{ {
@ -12,13 +15,46 @@ namespace WebAPI.Controllers
[ApiController] [ApiController]
public class LogController : ApiControllerBase<LogInfo> public class LogController : ApiControllerBase<LogInfo>
{ {
public LogController(ICrudLogic<LogInfo> logic) : base(logic) private readonly ILoggingService loggingService;
public LogController(
ICrudLogic<LogInfo> logic,
ILoggingService loggingService
) : base(logic)
{ {
this.loggingService = loggingService;
} }
[HttpPost] [HttpPost]
public void PurgeBefore([FromBody] DateTime date) public void PurgeBefore([FromBody] DateTime date)
{ {
logic.Delete(l => l.Time <= date.ToUniversalTime()); logic.Delete(l => l.Time <= date.ToUniversalTime());
} }
[Route("/error-development")]
public IActionResult HandleErrorDevelopment(
[FromServices] IHostEnvironment hostEnvironment)
{
if (!hostEnvironment.IsDevelopment())
{
return NotFound();
}
var exceptionHandlerFeature =
HttpContext.Features.Get<IExceptionHandlerFeature>()!;
this.loggingService.Error(exceptionHandlerFeature.Error, exceptionHandlerFeature.Path);
return Problem(
detail: exceptionHandlerFeature.Error.StackTrace,
title: exceptionHandlerFeature.Error.Message);
}
[Route("/error")]
public IActionResult HandleError()
{
var exceptionHandlerFeature =
HttpContext.Features.Get<IExceptionHandlerFeature>()!;
this.loggingService.Error(exceptionHandlerFeature.Error, exceptionHandlerFeature.Path);
return Problem();
}
} }
} }

View File

@ -1,4 +1,5 @@
using Church.Net.DAL.EF; using Church.Net.DAL.EF;
using Church.Net.DAL.EFCoreDBF;
using Church.Net.Entity; using Church.Net.Entity;
using Church.Net.Utility; using Church.Net.Utility;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
@ -28,17 +29,16 @@ namespace WebAPI.Controllers
// POST api/<PasswordLoginController> // POST api/<PasswordLoginController>
public PasswordLoginController( public PasswordLoginController(
ChurchNetContext churchNetContext,
ICrudLogic<FamilyMember> crudLogic, ICrudLogic<FamilyMember> crudLogic,
ICombinedKeyCrudLogic<PastoralDomainMembers> relationLogic, ICombinedKeyCrudLogic<PastoralDomainMembers> relationLogic,
ICrudLogic<PastoralDomain> domainLogic ICrudLogic<PastoralDomain> domainLogic,
DatabaseOptions databaseOptions
) )
{ {
this.churchNetContext = churchNetContext;
this.crudLogic = crudLogic; this.crudLogic = crudLogic;
this.relationLogic = relationLogic; this.relationLogic = relationLogic;
this.domainLogic = domainLogic; this.domainLogic = domainLogic;
churchNetContext = databaseOptions.GetDbContext();
} }
[HttpPost] [HttpPost]
[Route("auth/login")] [Route("auth/login")]

View File

@ -68,14 +68,14 @@ namespace WebAPI.Controllers
bool isGet = methodInfo.GetCustomAttributes(typeof(HttpGetAttribute), false).Length > 0; bool isGet = methodInfo.GetCustomAttributes(typeof(HttpGetAttribute), false).Length > 0;
bool isPost = methodInfo.GetCustomAttributes(typeof(HttpPostAttribute), false).Length > 0; bool isPost = methodInfo.GetCustomAttributes(typeof(HttpPostAttribute), false).Length > 0;
bool isDelete = methodInfo.GetCustomAttributes(typeof(HttpDeleteAttribute), false).Length > 0; bool isDelete = methodInfo.GetCustomAttributes(typeof(HttpDeleteAttribute), false).Length > 0;
if(isGet|| isPost|| isDelete) if (isGet || isPost || isDelete)
{ {
Endpoint _endpoint = new Endpoint Endpoint _endpoint = new Endpoint
{ {
Name = methodInfo.Name, Name = methodInfo.Name,
Method = isGet ? "GET" : (isPost ? "POST" : (isDelete ? "DELETE" : "UNKNOWN")), Method = isGet ? "GET" : (isPost ? "POST" : (isDelete ? "DELETE" : "UNKNOWN")),
Inputs = methodInfo.GetParameters().Select(m=>new Input() { Name=m.Name}).ToArray(), Inputs = methodInfo.GetParameters().Select(m => new Input() { Name = m.Name }).ToArray(),
ReturnType = methodInfo.ReturnType, ReturnType = methodInfo.ReturnType,
//MethodInfo = methodInfo, //MethodInfo = methodInfo,
}; };
@ -92,7 +92,7 @@ namespace WebAPI.Controllers
} }
return _controllers; return _controllers;
} }
[HttpGet] [HttpGet]
public async void TestMessage() public async void TestMessage()
{ {
@ -112,7 +112,7 @@ namespace WebAPI.Controllers
Uri = "https://happiness.tours/CellGroup/prayer?openExternalBrowser=1", Uri = "https://happiness.tours/CellGroup/prayer?openExternalBrowser=1",
Label = "Prayer" Label = "Prayer"
}; };
templateMessage.AltText= "代禱事項"; templateMessage.AltText = "代禱事項";
templateMessage.Template.DefaultAction = addPrayerBtn; templateMessage.Template.DefaultAction = addPrayerBtn;
templateMessage.Template.ThumbnailImageUrl = "https://dailyverses.net/images/tc/cuv/matthew-21-22-3.jpg"; templateMessage.Template.ThumbnailImageUrl = "https://dailyverses.net/images/tc/cuv/matthew-21-22-3.jpg";
@ -120,11 +120,11 @@ namespace WebAPI.Controllers
templateMessage.Template.Title = "代禱事項"; templateMessage.Template.Title = "代禱事項";
templateMessage.Template.Text = "Chris" + Environment.NewLine + "Testwerewiorjowerjiowejiro, erjaiworjweiorjioawereaw"; templateMessage.Template.Text = "Chris" + Environment.NewLine + "Testwerewiorjowerjiowejiro, erjaiworjweiorjioawereaw";
templateMessage.Template.Actions = new List<ILineAction>(); templateMessage.Template.Actions = new List<ILineAction>();
templateMessage.Template.Actions.Add(addPrayerBtn); templateMessage.Template.Actions.Add(addPrayerBtn);
await test.PushMessage(EnumHelper.EnumToDescriptionString(LineGroup.Chris), textMessage); await test.PushMessage(EnumHelper.EnumToDescriptionString(LineGroup.Chris), textMessage);
} }
@ -151,7 +151,7 @@ namespace WebAPI.Controllers
} }
else else
{ {
// ReplyTextMessage(replyToken, autoReply.ReplyMessage); // ReplyTextMessage(replyToken, autoReply.ReplyMessage);
} }
return; return;
@ -162,6 +162,14 @@ namespace WebAPI.Controllers
}; };
} }
[HttpGet]
public string[] GetFiles(string path)
{
return Directory.GetFiles("/App_Data/" + path);
}
public class Controller public class Controller
{ {
public string Name { get; set; } public string Name { get; set; }

View File

@ -2,6 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;

View File

@ -9,7 +9,7 @@ FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /src WORKDIR /src
COPY ["WebAPI/WebAPI.csproj", "WebAPI/"] COPY ["WebAPI/WebAPI.csproj", "WebAPI/"]
COPY ["Church.Net.DAL.EFCoreDBF/Church.Net.DAL.EFCoreDBF.csproj", "Church.Net.DAL.EFCoreDBF/"] COPY ["Church.Net.DAL.EFCoreDBF/Church.Net.DAL.EFCoreDBF.csproj", "Church.Net.DAL.EFCoreDBF/"]
COPY ["Church.Net.Entity2/Church.Net.Entity2.csproj", "Church.Net.Entity2/"] COPY ["Church.Net.Entity2/Church.Net.Entity.csproj", "Church.Net.Entity/"]
COPY ["Church.Net.Utility/Church.Net.Utility.csproj", "Church.Net.Utility/"] COPY ["Church.Net.Utility/Church.Net.Utility.csproj", "Church.Net.Utility/"]
RUN dotnet restore "WebAPI/WebAPI.csproj" RUN dotnet restore "WebAPI/WebAPI.csproj"
COPY . . COPY . .

View File

@ -0,0 +1,43 @@
namespace WebAPI.Handlers
{
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Authorization.Policy;
using Microsoft.AspNetCore.Http;
using System.Linq;
using System.Threading.Tasks;
public class BasicAuthorizationMiddlewareResultHandler : IAuthorizationMiddlewareResultHandler
{
private readonly AuthorizationMiddlewareResultHandler defaultHandler = new();
public async Task HandleAsync(
RequestDelegate next,
HttpContext context,
AuthorizationPolicy policy,
PolicyAuthorizationResult authorizeResult)
{
// If the authorization was forbidden and the resource had a specific requirement,
// provide a custom 404 response.
if (authorizeResult.Forbidden
&& authorizeResult.AuthorizationFailure!.FailedRequirements
.OfType<Show404Requirement>().Any())
{
// Return a 404 to make it appear as if the resource doesn't exist.
context.Response.StatusCode = StatusCodes.Status404NotFound;
return;
}
if (string.IsNullOrWhiteSpace(context.Request.Headers["accessToken"]))
{
context.Response.StatusCode = StatusCodes.Status401Unauthorized;
return;
}
// Fall back to the default implementation.
//await defaultHandler.HandleAsync(next, context, policy, authorizeResult);
await next(context);
}
}
public class Show404Requirement : IAuthorizationRequirement { }
}

View File

@ -7,21 +7,25 @@ using System;
using WebAPI.Logics.Core; using WebAPI.Logics.Core;
using WebAPI.Logics.Interface; using WebAPI.Logics.Interface;
using System.Linq; using System.Linq;
using Microsoft.Extensions.DependencyInjection;
namespace WebAPI.Logics namespace WebAPI.Logics
{ {
public class CellGroupLogic public class CellGroupLogic
{ {
private readonly IServiceScopeFactory serviceScopeFactory;
private readonly ICrudDAL<CellGroupRoutineEvent> eventCrudDAL; private readonly ICrudDAL<CellGroupRoutineEvent> eventCrudDAL;
private readonly ICombinedKeyCrudDAL<CellGroupRoutineEventAttendee> attendeeCrudDAL; private readonly ICombinedKeyCrudDAL<CellGroupRoutineEventAttendee> attendeeCrudDAL;
private readonly ICrudDAL<FamilyMember> memberCrudDAL; private readonly ICrudDAL<FamilyMember> memberCrudDAL;
public CellGroupLogic( public CellGroupLogic(
IServiceScopeFactory serviceScopeFactory,
ICrudDAL<CellGroupRoutineEvent> eventCrudDAL, ICrudDAL<CellGroupRoutineEvent> eventCrudDAL,
ICombinedKeyCrudDAL<CellGroupRoutineEventAttendee> attendeeCrudDAL, ICombinedKeyCrudDAL<CellGroupRoutineEventAttendee> attendeeCrudDAL,
ICrudDAL<FamilyMember> memberCrudDAL ICrudDAL<FamilyMember> memberCrudDAL
) )
{ {
this.serviceScopeFactory = serviceScopeFactory;
this.eventCrudDAL = eventCrudDAL; this.eventCrudDAL = eventCrudDAL;
this.attendeeCrudDAL = attendeeCrudDAL; this.attendeeCrudDAL = attendeeCrudDAL;
this.memberCrudDAL = memberCrudDAL; this.memberCrudDAL = memberCrudDAL;

View File

@ -13,8 +13,8 @@ namespace WebAPI.Logics.Core
{ {
public class LogicBase<T> : ICrudLogic<T> where T : class, Church.Net.Entity.Interface.IEntity, new() public class LogicBase<T> : ICrudLogic<T> where T : class, Church.Net.Entity.Interface.IEntity, new()
{ {
private readonly LogicService logicService; protected readonly LogicService logicService;
private readonly ICrudDAL<T> crudDAL; protected readonly ICrudDAL<T> crudDAL;
public LogicBase( public LogicBase(
LogicService logicService, LogicService logicService,
@ -46,15 +46,15 @@ namespace WebAPI.Logics.Core
public int CreateOrUpdate(T entity, out string id) public int CreateOrUpdate(T entity, out string id)
{ {
var result= this.crudDAL.CreateOrUpdate(entity, out string _id); var result= this.crudDAL.CreateOrUpdate(entity);
id = _id; id = entity.Id;
return result; return result;
} }
public string CreateReturnId(T entity) //public string CreateReturnId(T entity)
{ //{
return this.crudDAL.CreateReturnId(entity); // return this.crudDAL.CreateReturnId(entity);
} //}
public int Delete(T obj) public int Delete(T obj)
{ {
@ -75,10 +75,10 @@ namespace WebAPI.Logics.Core
return this.crudDAL.GetAll(filter); return this.crudDAL.GetAll(filter);
} }
public IEnumerable<T> GetAllById(IEnumerable<string> Ids) //public IEnumerable<T> GetAllById(IEnumerable<string> Ids)
{ //{
return this.crudDAL.GetAllById(Ids); // return this.crudDAL.GetAllById(Ids);
} //}
public T GetById(string Id) public T GetById(string Id)
{ {

View File

@ -1,16 +1,33 @@
using Church.Net.DAL.EF; using Church.Net.DAL.EF;
using Microsoft.Extensions.DependencyInjection;
using WebAPI.Services;
namespace WebAPI.Logics.Core namespace WebAPI.Logics.Core
{ {
public class LogicService public class LogicService
{ {
private readonly IServiceScopeFactory serviceScopeFactory;
public LogicService( public LogicService(
ChurchNetContext dbContext //ChurchNetContext dbContext
IServiceScopeFactory serviceScopeFactory
) )
{ {
DbContext = dbContext; this.serviceScopeFactory = serviceScopeFactory;
//DbContext = dbContext;
} }
public ChurchNetContext DbContext { get; } //public ChurchNetContext DbContext { get; }
public string CurrentUserId
{
get
{
using (var scope = serviceScopeFactory.CreateScope())
{
var service = scope.ServiceProvider.GetService<IdentityService>();
return service.UserId;
}
}
}
} }
} }

View File

@ -37,7 +37,7 @@ namespace WebAPI.Logics
{ {
var week = GetHappinessWeek(group, i); var week = GetHappinessWeek(group, i);
group.Weeks.Add(week); group.Weeks.Add(week);
weekCrudDAL.CreateOrUpdate(week, out string weekId); weekCrudDAL.CreateOrUpdate(week);
} }
} }
group.Weeks = group.Weeks.OrderBy(w => w.SEQ).ToList(); group.Weeks = group.Weeks.OrderBy(w => w.SEQ).ToList();
@ -66,7 +66,7 @@ namespace WebAPI.Logics
} }
return weekCrudDAL.UpdateRange(list); return weekCrudDAL.UpdateRange(list);
} }
return weekCrudDAL.CreateOrUpdate(value, out string id); return weekCrudDAL.CreateOrUpdate(value);
} }

View File

@ -13,10 +13,10 @@ namespace WebAPI.Logics.Interface
T GetById(string Id); T GetById(string Id);
IEnumerable<T> GetAll(Func<T, bool> filter = null); IEnumerable<T> GetAll(Func<T, bool> filter = null);
IEnumerable<T> GetAllById(IEnumerable<string> Ids); //IEnumerable<T> GetAllById(IEnumerable<string> Ids);
int Create(T entity); int Create(T entity);
Task<int> CreateAsync(T entity); Task<int> CreateAsync(T entity);
string CreateReturnId(T entity); //string CreateReturnId(T entity);
int CreateOrUpdate(T entity, out string id); int CreateOrUpdate(T entity, out string id);
int Update(T entity); int Update(T entity);

View File

@ -0,0 +1,49 @@
using Church.Net.DAL.EFCoreDBF;
using Church.Net.Entity;
using Church.Net.Entity.Interface;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using WebAPI.Logics.Core;
using WebAPI.Logics.Interface;
namespace WebAPI.Logics
{
public class LineMessagingAccountLogic : LogicBase<LineMessagingAccount>, ICrudLogic<LineMessagingAccount>
{
private readonly ICrudDAL<HappinessGroup> happinessGroupDAL;
private readonly ICrudDAL<PastoralDomain> cellGroupDAL;
public LineMessagingAccountLogic(
LogicService logicService,
ICrudDAL<LineMessagingAccount> crudDAL,
ICrudDAL<HappinessGroup> happinessGroupDAL,
ICrudDAL<PastoralDomain> cellGroupDAL
) : base(logicService, crudDAL)
{
this.happinessGroupDAL = happinessGroupDAL;
this.cellGroupDAL = cellGroupDAL;
}
public HappinessGroup GetHappinessGroup(string lineGroupId)
{
var group= happinessGroupDAL.First(c => c.CommunityAppId == lineGroupId);
GetLineMessagingAccount(group);
return group;
}
public PastoralDomain GetCellGroup(string lineGroupId)
{
var group = cellGroupDAL.First(c => c.CommunityAppId == lineGroupId);
GetLineMessagingAccount(group);
return group;
}
private void GetLineMessagingAccount(IMessengerClient messengerClient)
{
if (messengerClient != null)
{
messengerClient.LineMessagingAccount = crudDAL.GetById(messengerClient.LineAccountId);
}
}
}
}

View File

@ -16,10 +16,9 @@ namespace WebAPI.Services.AutoReplyCommands
public class ArArkCellGroupDinner : IAutoReplyCommand public class ArArkCellGroupDinner : IAutoReplyCommand
{ {
public ArArkCellGroupDinner(ChurchNetContext context, public ArArkCellGroupDinner(
CellGroupLogic logic) CellGroupLogic logic)
{ {
this._context = context;
this.logic = logic; this.logic = logic;
} }
private static readonly string[] COMMANDS = { "晚餐", "dinner" }; private static readonly string[] COMMANDS = { "晚餐", "dinner" };
@ -28,57 +27,12 @@ namespace WebAPI.Services.AutoReplyCommands
LineGroup.Ark, LineGroup.Ark,
LineGroup.Chris, LineGroup.Chris,
}; };
private readonly ChurchNetContext _context;
private readonly CellGroupLogic logic; private readonly CellGroupLogic logic;
public string Description => "顯示方舟小組聚會晚餐"; public string Description => "顯示方舟小組聚會晚餐";
public IEnumerable<string> Commands => COMMANDS; public IEnumerable<string> Commands => COMMANDS;
public IEnumerable<LineGroup> SupportGroups => GROUPS; public IEnumerable<LineGroup> SupportGroups => GROUPS;
public IEnumerable<string> ReplyMessage public IEnumerable<string> ReplyMessage => null;
{
get
{
StringBuilder sb = new StringBuilder();
StringBuilder comments = new StringBuilder();
sb.AppendLine("又到了令人期待的小組日~~~");
var _event = _context.CellGroupRoutineEvents.Where(e => e.Time >= DateTime.Today)
.Include(e => e.Attendees).FirstOrDefault();
if (_event == null)
{
_event = new CellGroupRoutineEvent()
{
Id = Format.Get33BaseGuid(),
Time = DateTimeHelper.GetNextWeekday(DateTime.Today, DayOfWeek.Friday).AddHours(19).AddMinutes(30),
Address = "1881 Forest Dr., Azusa, CA 91702",
Attendees = new List<CellGroupRoutineEventAttendee>()
};
_context.Add(_event);
_context.SaveChanges();
}
sb.AppendLine($"{_event.Time.ToString("MM/dd HH:mm tt")} 開飯~");
sb.AppendLine("======= 晚宴清單 =======");
foreach (var a in _event.Attendees)
{
sb.AppendLine($"{a.Name} - {string.Join(", ", a.PotluckItem.Split('|'))}");
if (!string.IsNullOrWhiteSpace(a.Comment))
{
comments.AppendLine($"{a.Name}:{a.Comment}");
}
}
if (comments.Length > 0)
{
sb.AppendLine("========= 備註 =========");
sb.Append(comments.ToString());
}
return new string[] { sb.ToString() };
}
}
public IEnumerable<ILineMessage> LineMessage public IEnumerable<ILineMessage> LineMessage
{ {

View File

@ -231,7 +231,8 @@ namespace WebAPI.Services.AutoReplyCommands
{ {
Size = FlexObjectSize.sm, Size = FlexObjectSize.sm,
Color = "#666666", Color = "#666666",
Flex = 5 Flex = 5,
Wrap = true
}); });
comments.Add(commentLineBox); comments.Add(commentLineBox);
} }

View File

@ -127,12 +127,12 @@ namespace WebAPI.Services
EventLog.WriteEntry("BeyondAPI", $"Can Not Append Error Log:{ex.Message}", EventLogEntryType.Error); EventLog.WriteEntry("BeyondAPI", $"Can Not Append Error Log:{ex.Message}", EventLogEntryType.Error);
} }
public void Log(string message, object detail) public void Log(string message, object detail = null)
{ {
LogInfo log = new LogInfo(LogLevel.Info) LogInfo log = new LogInfo(LogLevel.Info)
{ {
Message = message, Message = message,
DetailMessage = JsonConvert.SerializeObject(detail,Formatting.Indented) , DetailMessage = JsonConvert.SerializeObject(detail, Formatting.Indented),
//Source = exception.Source, //Source = exception.Source,
//StackTrace = exception.StackTrace //StackTrace = exception.StackTrace
}; };

View File

@ -0,0 +1,26 @@
using Church.Net.Entity;
using Church.Net.Utility;
using Microsoft.AspNetCore.SignalR;
namespace WebAPI.Services
{
public class IdentityService
{
public string UserAccessToken { get; set; }
public string UserId { get; set; }
public PastoralDomain CellGroup
{
get {
TokenHelper.GetUserIdFromToken
return null; }
}
}
}

View File

@ -7,7 +7,7 @@ namespace WebAPI.Services.Interfaces
{ {
public interface ILoggingService public interface ILoggingService
{ {
void Log(string message, object detail); void Log(string message, object detail=null);
void Warning(string message, object detail); void Warning(string message, object detail);
int Error(Exception exception); int Error(Exception exception);
int Error(Exception exception, string from); int Error(Exception exception, string from);

View File

@ -0,0 +1,15 @@
using LineMessaging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace WebAPI.Services.Interfaces
{
public interface IScheduledTask
{
string Description { get; }
bool CheckTime(DateTime time);
Task<bool> RunTask();
}
}

View File

@ -1,4 +1,5 @@
using Church.Net.Utility; using Church.Net.Entity.Messenger;
using Church.Net.Utility;
using LineMessaging; using LineMessaging;
using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Logging.Abstractions;
using Newtonsoft.Json; using Newtonsoft.Json;
@ -8,6 +9,7 @@ using System.ComponentModel;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using WebAPI.Logics.Interface;
using WebAPI.Services.Interfaces; using WebAPI.Services.Interfaces;
using static System.Net.Mime.MediaTypeNames; using static System.Net.Mime.MediaTypeNames;
@ -27,14 +29,17 @@ namespace WebAPI.Services
{ {
private readonly IEnumerable<IAutoReplyCommand> autoReplyCommands; private readonly IEnumerable<IAutoReplyCommand> autoReplyCommands;
private readonly ILoggingService loggingService; private readonly ILoggingService loggingService;
private readonly ICrudLogic<LineMessageClient> clientLogic;
public LineAutoBotService( public LineAutoBotService(
IEnumerable<IAutoReplyCommand> autoReplyCommands, IEnumerable<IAutoReplyCommand> autoReplyCommands,
ILoggingService loggingService ILoggingService loggingService,
ICrudLogic<LineMessageClient> clientLogic
) )
{ {
this.autoReplyCommands = autoReplyCommands; this.autoReplyCommands = autoReplyCommands;
this.loggingService = loggingService; this.loggingService = loggingService;
this.clientLogic = clientLogic;
} }
public void SendTextMessage(string text, LineGroup target) public void SendTextMessage(string text, LineGroup target)
{ {
@ -72,7 +77,12 @@ namespace WebAPI.Services
} }
catch (Exception ex) catch (Exception ex)
{ {
this.loggingService.Error(ex, "ReplyTextMessage:68", JsonConvert.SerializeObject(replyMessage, Formatting.Indented)); this.loggingService.Error(ex, "ReplyTextMessage:75", JsonConvert.SerializeObject(replyMessage, Formatting.Indented));
if (ex.Message == "You have reached your monthly limit.")
{
this.SendTextMessage("Line Bot Exist Monthly Limit!!!", LineGroup.Chris);
}
return false; return false;
} }
} }
@ -92,7 +102,11 @@ namespace WebAPI.Services
} }
catch (Exception ex) catch (Exception ex)
{ {
this.loggingService.Error(ex, "ReplyLineMessage:84", JsonConvert.SerializeObject(replyMessage, Formatting.Indented)); this.loggingService.Error(ex, "ReplyLineMessage:95", JsonConvert.SerializeObject(replyMessage, Formatting.Indented));
if (ex.Message == "You have reached your monthly limit.")
{
this.SendTextMessage("Line Bot Exist Monthly Limit!!!", LineGroup.Chris);
}
return false; return false;
} }
@ -112,10 +126,13 @@ namespace WebAPI.Services
string replyToken = e.ReplyToken; string replyToken = e.ReplyToken;
string text = e.Message.Text; string text = e.Message.Text;
string target = ""; string target = "";
bool isGroup = true;
var client = new LineMessagingClient();
switch (e.Source.Type) switch (e.Source.Type)
{ {
case WebhookRequestSourceType.User: case WebhookRequestSourceType.User:
target = e.Source.UserId; target = e.Source.UserId;
isGroup = false;
break; break;
case WebhookRequestSourceType.Group: case WebhookRequestSourceType.Group:
target = e.Source.GroupId; target = e.Source.GroupId;
@ -127,6 +144,33 @@ namespace WebAPI.Services
default: default:
break; break;
} }
if (isGroup)
{
if (clientLogic.First(c => c.ClientId == e.Source.GroupId) == null)
{
clientLogic.CreateOrUpdate(new LineMessageClient()
{
ClientId = target,
Name = client.GetGroupProfile(e.Source.GroupId).Result.GroupName,
IsGroup = true
}, out string id);
}
//TODO:Get user by user id under group
}
else
{
if (clientLogic.First(c => c.ClientId == e.Source.UserId) == null)
{
clientLogic.CreateOrUpdate(new LineMessageClient()
{
ClientId = target,
Name = client.GetProfile(e.Source.UserId).Result.DisplayName,
IsGroup = false
}, out string id);
}
}
if (!String.IsNullOrWhiteSpace(replyToken) && text.IndexOf("#") == 0) if (!String.IsNullOrWhiteSpace(replyToken) && text.IndexOf("#") == 0)
{ {
@ -166,8 +210,12 @@ namespace WebAPI.Services
} }
else if (e.Message.Type == MessageType.Sticker && e.Source.GroupId == LineGroup.Ark.EnumToDescriptionString() && e.Message.PackageId == "1011092" && e.Message.StickerId == "510712")
{
await ReplyLineMessage(e.Source.GroupId, autoReplyCommands.Where(ar => ar.Commands.Contains("pray")).FirstOrDefault().LineMessage);
}
this.LogLineMessage(e);
} }
} }
catch (Exception ex) catch (Exception ex)
@ -224,7 +272,7 @@ namespace WebAPI.Services
} }
catch (Exception ex) catch (Exception ex)
{ {
loggingService.Error(ex, "AutoReply:188",command); loggingService.Error(ex, "AutoReply:188", command);
return false; return false;
} }
@ -232,64 +280,5 @@ namespace WebAPI.Services
return true; return true;
} }
private void LogLineMessage(LineWebhookContent.Event e)
{
return;
try
{
//var lineHookRequest = new LineMessaging.LineWebhookRequest("d23edf453427256a759d218ec8b6779f", request);
//var content = await lineHookRequest.GetContent();
string txtPath = ServerUtils.MapPath("App_Data/LinePostLog.txt");
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.AppendLine($"==================={DateTime.Now.ToString("MM/dd/yyyy HH:mm")}=========================");
stringBuilder.AppendLine($"Message Type:{e.Type.ToString()}");
switch (e.Source.Type)
{
case WebhookRequestSourceType.User:
stringBuilder.AppendLine($"UserId:{e.Source.UserId}");
break;
case WebhookRequestSourceType.Group:
stringBuilder.AppendLine($"GroupId:{e.Source.GroupId}");
break;
case WebhookRequestSourceType.Room:
stringBuilder.AppendLine($"RoomId:{e.Source.RoomId}");
break;
default:
break;
}
stringBuilder.AppendLine($"Reply Token:{e.ReplyToken}");
stringBuilder.AppendLine($"Message Type:{e.Message.Type.ToString()}");
switch (e.Message.Type)
{
case MessageType.Text:
stringBuilder.AppendLine($"Message:{e.Message.Text}");
break;
case MessageType.Image:
case MessageType.Video:
case MessageType.Audio:
case MessageType.File:
case MessageType.Location:
case MessageType.Sticker:
case MessageType.Imagemap:
case MessageType.Template:
default:
stringBuilder.AppendLine($"Message:{JsonConvert.SerializeObject(e.Message, Formatting.Indented)}");
break;
}
System.IO.File.AppendAllText(txtPath, stringBuilder.ToString());
}
catch (Exception ex)
{
}
}
} }
} }

View File

@ -0,0 +1,46 @@
using Church.Net.Utility;
using System;
using System.Threading.Tasks;
using WebAPI.Services.Interfaces;
namespace WebAPI.Services.ScheduledTask
{
public class MorningPrayer : IScheduledTask
{
private readonly LineAutoBotService lineAutoBotService;
private readonly ILoggingService loggingService;
private DateTime? nextRunningTime = null;
public MorningPrayer(
LineAutoBotService lineAutoBotService,
ILoggingService loggingService
)
{
this.lineAutoBotService = lineAutoBotService;
this.loggingService = loggingService;
this.SetNextRunningTime();
}
public string Description => "Sent out Ark Morning Prayer";
public bool CheckTime(DateTime time)
{
if(nextRunningTime == null)
{
this.SetNextRunningTime();
return true;
}
return time >= nextRunningTime.Value;
}
public Task<bool> RunTask()
{
SetNextRunningTime();
return lineAutoBotService.PushCommandMessage(LineGroup.Ark, "#pray");
}
private void SetNextRunningTime()
{
nextRunningTime = DateTimeHelper.Today().AddDays(1).AddHours(8);
loggingService.Log($"Scheduled Task {this.Description}", nextRunningTime.Value);
}
}
}

View File

@ -0,0 +1,70 @@
using Microsoft.Extensions.Hosting;
using System.Threading.Tasks;
using System.Threading;
using System;
using WebAPI.Services.Interfaces;
using System.Collections.Generic;
using System.Linq;
using Church.Net.Utility;
using Microsoft.AspNetCore.Hosting;
namespace WebAPI.Services
{
public class WorkerService : BackgroundService
{
private IEnumerable<IScheduledTask> scheduledTasks;
private ILoggingService loggingService;
private readonly IWebHostEnvironment env;
private static bool initialized = false;
public WorkerService(
IEnumerable<IScheduledTask> scheduledTasks,
ILoggingService loggingService
)
{
this.scheduledTasks = scheduledTasks;
this.loggingService = loggingService;
}
private const int generalDelay = 5 * 60 * 1000; // 10 seconds
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
//await DoBackupAsync();
while (!stoppingToken.IsCancellationRequested)
{
await Task.Delay(generalDelay, stoppingToken);
await DoBackupAsync();
}
}
private async Task<string> DoBackupAsync()
{
// here i can write logic for taking backup at midnight
//if (IsMidnight())
//{
// Console.WriteLine("Executing background task");
// TakeBackup();
//}
var now = DateTimeHelper.Now();
foreach (var worker in scheduledTasks)
{
try
{
if (worker.CheckTime(now))
{
loggingService.Log($"Running {worker.Description}");
await worker.RunTask();
}
}
catch (Exception ex)
{
loggingService.Error(ex, worker.Description);
}
}
return "Done";
}
}
}

View File

@ -6,6 +6,7 @@ using System.Threading.Tasks;
using Church.Net.DAL.EF; using Church.Net.DAL.EF;
using Church.Net.DAL.EFCoreDBF; using Church.Net.DAL.EFCoreDBF;
using Church.Net.Entity; using Church.Net.Entity;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Diagnostics; using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
@ -18,6 +19,7 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Newtonsoft.Json.Serialization; using Newtonsoft.Json.Serialization;
using WebAPI.Handlers;
using WebAPI.Hubs; using WebAPI.Hubs;
using WebAPI.Logics; using WebAPI.Logics;
using WebAPI.Logics.Core; using WebAPI.Logics.Core;
@ -25,6 +27,7 @@ using WebAPI.Logics.Interface;
using WebAPI.Services; using WebAPI.Services;
using WebAPI.Services.AutoReplyCommands; using WebAPI.Services.AutoReplyCommands;
using WebAPI.Services.Interfaces; using WebAPI.Services.Interfaces;
using WebAPI.Services.ScheduledTask;
using static System.Net.Mime.MediaTypeNames; using static System.Net.Mime.MediaTypeNames;
namespace WebAPI namespace WebAPI
@ -51,7 +54,7 @@ namespace WebAPI
NamingStrategy = new CamelCaseNamingStrategy(), NamingStrategy = new CamelCaseNamingStrategy(),
}; };
options.SerializerSettings.DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Unspecified; //options.SerializerSettings.DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Unspecified;
options.SerializerSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore; options.SerializerSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore;
options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore; options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
}); });
@ -60,6 +63,7 @@ namespace WebAPI
services.AddSignalR(); services.AddSignalR();
services.AddSingleton<GameRoomLogic>(); services.AddSingleton<GameRoomLogic>();
services.AddSingleton(_ => new DatabaseOptions { ConnectionString = "Host=192.168.86.131;Port=49154;Database=Church;Username=chris;Password=1124" });
//services.AddSingleton<ChurchNetContext>(new ChurchNetContext()); //services.AddSingleton<ChurchNetContext>(new ChurchNetContext());
services.AddDbContext<ChurchNetContext>(options => services.AddDbContext<ChurchNetContext>(options =>
options.UseNpgsql( options.UseNpgsql(
@ -67,30 +71,37 @@ namespace WebAPI
"Host=192.168.86.131;Port=49154;Database=Church;Username=chris;Password=1124" "Host=192.168.86.131;Port=49154;Database=Church;Username=chris;Password=1124"
)); ));
services.AddTransient<LineAutoBotService>(); services.AddSingleton<LineAutoBotService>();
services.AddTransient<IAutoReplyCommand, ArChurchInfo>(); services.AddSingleton<IAutoReplyCommand, ArChurchInfo>();
services.AddTransient<IAutoReplyCommand, ArArkCellGroupInfo>(); services.AddSingleton<IAutoReplyCommand, ArArkCellGroupInfo>();
services.AddTransient<IAutoReplyCommand, ArArkCellGroupDinner>(); services.AddSingleton<IAutoReplyCommand, ArArkCellGroupDinner>();
services.AddTransient<IAutoReplyCommand, ArArkCellGroupPrayer>(); services.AddSingleton<IAutoReplyCommand, ArArkCellGroupPrayer>();
services.AddSingleton<IScheduledTask, MorningPrayer>();
services.AddSingleton<VideoDownloadLogic>(); services.AddSingleton<VideoDownloadLogic>();
services.AddScoped<LogicService>(); services.AddSingleton<LogicService>();
services.AddScoped<CellGroupLogic>(); services.AddSingleton<CellGroupLogic>();
services.AddScoped(typeof(ICrudLogic<>), typeof(LogicBase<>)); services.AddSingleton(typeof(ICrudLogic<>), typeof(LogicBase<>));
services.AddScoped(typeof(ICrudDAL<>), typeof(CrudDALCBase<>)); services.AddSingleton(typeof(ICrudDAL<>), typeof(CrudDALCBase<>));
services.AddScoped(typeof(ICombinedKeyCrudLogic<>), typeof(CombinedKeyLogicBase<>)); services.AddSingleton(typeof(ICombinedKeyCrudLogic<>), typeof(CombinedKeyLogicBase<>));
services.AddScoped(typeof(ICombinedKeyCrudDAL<>), typeof(CombinedKeyCrudDALCBase<>)); services.AddSingleton(typeof(ICombinedKeyCrudDAL<>), typeof(CombinedKeyCrudDALCBase<>));
services.AddScoped<HappinessGroupLogic>(); services.AddSingleton<HappinessGroupLogic>();
services.AddTransient<ILoggingService, DbLoggingService>(); services.AddSingleton<LineMessagingAccountLogic>();
services.AddSingleton<ILoggingService, DbLoggingService>();
services.AddScoped<IdentityService>();
services.AddHostedService<WorkerService>();
//services.AddMvc(o=>o.Filters.Add(typeof(HandleExceptionFilter))); //services.AddMvc(o=>o.Filters.Add(typeof(HandleExceptionFilter)));
//services.AddMvc(o => o.Filters.Add(new HandleExceptionFilter(services.BuildServiceProvider().GetService<ILoggingService>()))); //services.AddMvc(o => o.Filters.Add(new HandleExceptionFilter(services.BuildServiceProvider().GetService<ILoggingService>())));
//services.BuildServiceProvider().GetService<ILoggingService>(); //services.BuildServiceProvider().GetService<ILoggingService>();
services.AddSingleton<IAuthorizationMiddlewareResultHandler, BasicAuthorizationMiddlewareResultHandler>();
} }
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ChurchNetContext dbContext) public void Configure(IApplicationBuilder app, IWebHostEnvironment env, DatabaseOptions databaseOptions)
{ {
//Reference:https://stackoverflow.com/questions/69961449/net6-and-datetime-problem-cannot-write-datetime-with-kind-utc-to-postgresql-ty //Reference:https://stackoverflow.com/questions/69961449/net6-and-datetime-problem-cannot-write-datetime-with-kind-utc-to-postgresql-ty
@ -101,7 +112,12 @@ namespace WebAPI
AppDomain.CurrentDomain.SetData("WebRootPath", env.WebRootPath); AppDomain.CurrentDomain.SetData("WebRootPath", env.WebRootPath);
if (env.IsDevelopment()) if (env.IsDevelopment())
{ {
app.UseDeveloperExceptionPage(); //app.UseDeveloperExceptionPage();
app.UseExceptionHandler("/error-development");
}
else
{
app.UseExceptionHandler("/error");
} }
// global cors policy // global cors policy
@ -113,18 +129,16 @@ namespace WebAPI
.AllowCredentials() .AllowCredentials()
); // allow credentials ); // allow credentials
//app.UseCors(builder =>
//{
// builder.WithOrigins("http://localhost:4200")
// .AllowAnyHeader()
// .WithMethods("GET", "POST")
// .AllowCredentials();
//});
//app.UseHttpsRedirection(); //app.UseHttpsRedirection();
//app.UsePathBase(new PathString("/api")); //app.UsePathBase(new PathString("/api"));
app.UsePathBase(new PathString("/")); app.UsePathBase(new PathString("/"));
app.UseRouting(); app.UseRouting();
//app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints => app.UseEndpoints(endpoints =>
{ {
//endpoints.MapControllerRoute( //endpoints.MapControllerRoute(
@ -135,50 +149,19 @@ namespace WebAPI
endpoints.MapHub<BaseHub>("/BaseHub"); endpoints.MapHub<BaseHub>("/BaseHub");
endpoints.MapControllers(); endpoints.MapControllers();
//endpoints.MapControllerRoute( //endpoints.MapControllerRoute(
// name: "default", // name: "default",
// pattern: "{controller}/{action=Index}/{id?}"); // pattern: "{controller}/{action=Index}/{id?}");
}); });
//app.UseExceptionHandler(exceptionHandlerApp =>
//{
// exceptionHandlerApp.Run(async context =>
// {
// context.Response.StatusCode = StatusCodes.Status500InternalServerError;
// // using static System.Net.Mime.MediaTypeNames;
// context.Response.ContentType = Text.Plain;
// await context.Response.WriteAsync("An exception was thrown.");
// var exceptionHandlerPathFeature =
// context.Features.Get<IExceptionHandlerPathFeature>();
// if (exceptionHandlerPathFeature?.Error is FileNotFoundException)
// {
// await context.Response.WriteAsync(" The file was not found.");
// }
// if (exceptionHandlerPathFeature?.Path == "/")
// {
// await context.Response.WriteAsync(" Page: Home.");
// }
// });
//});
//app.UseAuthorization();
//app.UseEndpoints(endpoints =>
//{
// endpoints.MapControllers();
// endpoints.MapHub<WhoIsSpyHub>("/WhoIsSpyHub");
//});
if (env.IsDevelopment()) if (env.IsDevelopment())
{ {
databaseOptions.GetDbContext().Database.Migrate();
//new ChurchNetContext(databaseOptions.ConnectionString).Database.Migrate();
//dbContext.Database.EnsureCreated(); //dbContext.Database.EnsureCreated();
dbContext.Database.Migrate(); //dbContext.Database.Migrate();
} }
} }
} }
} }

View File

@ -17,6 +17,7 @@
<ItemGroup> <ItemGroup>
<Folder Include="App_Data\" /> <Folder Include="App_Data\" />
<Folder Include="Controllers\PasswordLogin\" /> <Folder Include="Controllers\PasswordLogin\" />
<Folder Include="Filters\" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@ -38,8 +39,10 @@
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.10.9" /> <PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.10.9" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="6.0.8" /> <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="6.0.8" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="QRCoder" Version="1.4.1" /> <PackageReference Include="QRCoder-ImageSharp" Version="0.9.0" />
<PackageReference Include="SharpGrabber.YouTube" Version="1.4.0" /> <PackageReference Include="SharpGrabber.YouTube" Version="1.4.0" />
<PackageReference Include="SixLabors.ImageSharp" Version="2.1.3" />
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta15" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>