|
|
@@ -5,6 +5,7 @@ using System.ComponentModel.DataAnnotations.Schema;
|
|
|
using System.Data.Common;
|
|
|
using System.Data.Entity;
|
|
|
using System.Data.Entity.Core.Common;
|
|
|
+using System.Data.Entity.Core.Metadata.Edm;
|
|
|
using System.Data.Entity.Infrastructure;
|
|
|
using System.Data.Entity.Infrastructure.Interception;
|
|
|
using System.Data.Entity.ModelConfiguration.Conventions;
|
|
|
@@ -14,6 +15,7 @@ using System.Data.SQLite.EF6;
|
|
|
using System.IO;
|
|
|
using System.Linq;
|
|
|
using System.Reflection;
|
|
|
+using System.Text;
|
|
|
using System.Text.RegularExpressions;
|
|
|
using System.Threading.Tasks;
|
|
|
using XdCxRhDW.Entity;
|
|
|
@@ -30,60 +32,24 @@ namespace XdCxRhDW.Repostory
|
|
|
|
|
|
public int pk { get; set; }
|
|
|
}
|
|
|
- class DbTableForeignKeyInfo
|
|
|
- {
|
|
|
- public string from { get; set; }
|
|
|
- }
|
|
|
- public class RHDWLogContext : DbContext
|
|
|
- {
|
|
|
- public string DbFile;
|
|
|
- public RHDWLogContext() : base("LogDbCon") //配置使用的连接名
|
|
|
- {
|
|
|
- //|DataDirectory|在mvc等程序中代表了App_Data,在普通程序中代表程序根目录
|
|
|
- var dbFile = Database.Connection.ConnectionString.Replace("Data Source=", "").Replace("|DataDirectory|\\", "");
|
|
|
- this.DbFile = dbFile;
|
|
|
- }
|
|
|
|
|
|
- protected override void OnModelCreating(DbModelBuilder modelBuilder)
|
|
|
- {
|
|
|
- this.Database.Log = msg =>
|
|
|
- {
|
|
|
- };
|
|
|
- modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
|
|
|
- modelBuilder.Configurations.AddFromAssembly(typeof(RHDWLogContext).Assembly);//自动加载Entity-Type
|
|
|
- var sqliteConnectionInitializer = new SqliteCreateDatabaseIfNotExists<RHDWLogContext>(modelBuilder);
|
|
|
- Database.SetInitializer(sqliteConnectionInitializer);
|
|
|
- base.OnModelCreating(modelBuilder);
|
|
|
- }
|
|
|
- public DbSet<LogRes> LogRes { set; get; }
|
|
|
- }
|
|
|
- /// <summary>
|
|
|
- /// 基础表上下文(id为int)
|
|
|
- /// </summary>
|
|
|
- public class RHDWContext : DbContext
|
|
|
+ public class DbContextBase : DbContext
|
|
|
{
|
|
|
- public string DbFile;
|
|
|
- public RHDWContext() : base("DbCon") //配置使用的连接名
|
|
|
+ public DbContextBase(string nameOrConnectionString)
|
|
|
+ : base(nameOrConnectionString)
|
|
|
{
|
|
|
- //|DataDirectory|在mvc等程序中代表了App_Data,在普通程序中代表程序根目录
|
|
|
- this.DbFile = Database.Connection.ConnectionString.Replace("Data Source=", "").Replace("|DataDirectory|\\", "");
|
|
|
}
|
|
|
|
|
|
- public Task<List<T>> SqlQueryAsync<T>(string sql)
|
|
|
+ public void SyncDb()
|
|
|
{
|
|
|
- return this.Database.SqlQuery<T>(sql).ToListAsync();
|
|
|
- }
|
|
|
- public Task<T> SqlQueryOneAsync<T>(string sql)
|
|
|
- {
|
|
|
- return this.Database.SqlQuery<T>(sql).FirstOrDefaultAsync();
|
|
|
-
|
|
|
+ SyncTable();
|
|
|
+ SyncTableField();
|
|
|
}
|
|
|
- //检查数据库表是否缺失
|
|
|
- public string CheckTableExist()
|
|
|
+ void SyncTable()
|
|
|
{
|
|
|
var tables = this.Database.SqlQuery<string>("select name from sqlite_master where type='table' and name not like 'sqlite%'").ToList();
|
|
|
var props = this.GetType().GetProperties();
|
|
|
- List<string> list = new List<string>();
|
|
|
+ Dictionary<string, Type> list = new Dictionary<string, Type>();
|
|
|
foreach (var prop in props)
|
|
|
{
|
|
|
bool isDbSet = prop.PropertyType.IsGenericType && typeof(DbSet<>) == prop.PropertyType.GetGenericTypeDefinition();
|
|
|
@@ -95,19 +61,60 @@ namespace XdCxRhDW.Repostory
|
|
|
{
|
|
|
name = entityType.Name;
|
|
|
}
|
|
|
- list.Add(name);
|
|
|
+ list.Add(name, entityType);
|
|
|
}
|
|
|
}
|
|
|
foreach (var item in list)
|
|
|
{
|
|
|
- if (!tables.Contains(item))
|
|
|
+ if (!tables.Contains(item.Key))
|
|
|
{
|
|
|
- return item;
|
|
|
+ var entityProps = item.Value.GetProperties().Where(p =>
|
|
|
+ p.CanRead
|
|
|
+ && p.CanWrite
|
|
|
+ && !p.GetMethod.IsVirtual
|
|
|
+ && p.GetCustomAttribute<NotMappedAttribute>() == null);
|
|
|
+ item.Value.GetProperties().Where(p => p.CanWrite);
|
|
|
+ StringBuilder sb = new StringBuilder();
|
|
|
+ sb.Append($"create table {item.Key}(ID integer primary key autoincrement");
|
|
|
+ foreach (var prop in entityProps)
|
|
|
+ {
|
|
|
+ if (prop.Name.ToLower() == "id") continue;
|
|
|
+ bool isNullable = prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>);
|
|
|
+ string typeStr = "";
|
|
|
+ var type = prop.PropertyType;
|
|
|
+ if (prop.PropertyType.IsGenericType)
|
|
|
+ {
|
|
|
+ type = prop.PropertyType.GenericTypeArguments[0];
|
|
|
+ }
|
|
|
+ if (type == typeof(string))
|
|
|
+ {
|
|
|
+ typeStr = "nvarchar";
|
|
|
+ }
|
|
|
+ else if (type == typeof(int) || type == typeof(long) || prop.PropertyType.IsEnum)
|
|
|
+ {
|
|
|
+ typeStr = "int";
|
|
|
+ }
|
|
|
+ else if (type == typeof(double) || type == typeof(float))
|
|
|
+ {
|
|
|
+ typeStr = "float";
|
|
|
+ }
|
|
|
+ else if (type == typeof(DateTime))
|
|
|
+ {
|
|
|
+ typeStr = "datetime";
|
|
|
+ }
|
|
|
+ sb.Append($",{prop.Name} {typeStr}");
|
|
|
+ if (!isNullable)
|
|
|
+ {
|
|
|
+ sb.Append(" not null");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ sb.Append(")");
|
|
|
+ string createTableSql = sb.ToString();
|
|
|
+ Database.ExecuteSqlCommand(createTableSql);
|
|
|
}
|
|
|
}
|
|
|
- return "";
|
|
|
}
|
|
|
- public string CheckTableField()
|
|
|
+ void SyncTableField()
|
|
|
{
|
|
|
var tables = this.Database.SqlQuery<string>("select name from sqlite_master where type='table' and name not like 'sqlite%'").ToList();
|
|
|
var props = this.GetType().GetProperties();
|
|
|
@@ -124,7 +131,8 @@ namespace XdCxRhDW.Repostory
|
|
|
foreach (var table in tables)
|
|
|
{
|
|
|
var res = this.Database.SqlQuery<DbTableColumnInfo>($"PRAGMA table_info([{table}])").ToList();
|
|
|
- var entityType = entityTypes.First(p => p.Name == table);
|
|
|
+ var entityType = entityTypes.FirstOrDefault(p => p.Name == table);
|
|
|
+ if (entityType == null) continue;
|
|
|
var entityProps = entityType.GetProperties().Where(p =>
|
|
|
p.CanRead
|
|
|
&& p.CanWrite
|
|
|
@@ -132,7 +140,7 @@ namespace XdCxRhDW.Repostory
|
|
|
&& p.GetCustomAttribute<NotMappedAttribute>() == null);
|
|
|
foreach (var prop in entityProps)
|
|
|
{
|
|
|
- var find = res.Find(p => p.name == prop.Name);
|
|
|
+ var find = res.Find(p => p.name.ToLower() == prop.Name.ToLower());
|
|
|
if (find == null)
|
|
|
{
|
|
|
string typeStr = "";
|
|
|
@@ -145,7 +153,7 @@ namespace XdCxRhDW.Repostory
|
|
|
{
|
|
|
typeStr = "nvarchar";
|
|
|
}
|
|
|
- else if (type == typeof(int) || type == typeof(long))
|
|
|
+ else if (type == typeof(int) || type == typeof(long) || prop.PropertyType.IsEnum)
|
|
|
{
|
|
|
typeStr = "int";
|
|
|
}
|
|
|
@@ -157,24 +165,76 @@ namespace XdCxRhDW.Repostory
|
|
|
{
|
|
|
typeStr = "datetime";
|
|
|
}
|
|
|
- return $"{DbFile}数据库表{table}缺少{prop.Name}字段,类型={typeStr}";
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
+ bool isNullable = prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>);
|
|
|
|
|
|
- if (prop.PropertyType != typeof(string) && find.pk == 0 && !prop.PropertyType.IsGenericType && find.notnull == 0)
|
|
|
+ string updateTableSql;
|
|
|
+ if (isNullable)
|
|
|
+ updateTableSql = $"alter table {table} add column {prop.Name} {typeStr}";
|
|
|
+ else
|
|
|
{
|
|
|
- var foreignInfo = this.Database.SqlQuery<DbTableForeignKeyInfo>($"PRAGMA foreign_key_list({table})").ToList();
|
|
|
- if (!foreignInfo.Any(p => p.from == prop.Name))
|
|
|
- {
|
|
|
- return $"{DbFile}数据库表{table}中{prop.Name}字段不允许为空";
|
|
|
- }
|
|
|
+ if (typeStr == "int" || typeStr == "float")
|
|
|
+ updateTableSql = $"alter table {table} add column {prop.Name} {typeStr} not null default 0";
|
|
|
+ else if (typeStr == "nvarchar")
|
|
|
+ updateTableSql = $"alter table {table} add column {prop.Name} {typeStr} not null default ''";
|
|
|
+ else if (typeStr == "datetime")
|
|
|
+ updateTableSql = $"alter table {table} add column {prop.Name} {typeStr} not null default '{DateTime.Now:yyyy-MM-dd HH:mm:ss}'";
|
|
|
+ else
|
|
|
+ updateTableSql = $"alter table {table} add column {prop.Name} {typeStr}";
|
|
|
}
|
|
|
+ this.Database.ExecuteSqlCommand(updateTableSql);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- return "";
|
|
|
}
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public class RHDWLogContext : DbContextBase
|
|
|
+ {
|
|
|
+ public string DbFile;
|
|
|
+ public RHDWLogContext() : base("LogDbCon") //配置使用的连接名
|
|
|
+ {
|
|
|
+ //|DataDirectory|在mvc等程序中代表了App_Data,在普通程序中代表程序根目录
|
|
|
+ var dbFile = Database.Connection.ConnectionString.Replace("Data Source=", "").Replace("|DataDirectory|\\", "");
|
|
|
+ this.DbFile = dbFile;
|
|
|
+ }
|
|
|
+
|
|
|
+ protected override void OnModelCreating(DbModelBuilder modelBuilder)
|
|
|
+ {
|
|
|
+ this.Database.Log = msg =>
|
|
|
+ {
|
|
|
+ };
|
|
|
+ modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
|
|
|
+ modelBuilder.Configurations.AddFromAssembly(typeof(RHDWLogContext).Assembly);//自动加载Entity-Type
|
|
|
+ var sqliteConnectionInitializer = new SqliteCreateDatabaseIfNotExists<RHDWLogContext>(modelBuilder);
|
|
|
+ Database.SetInitializer(sqliteConnectionInitializer);
|
|
|
+ base.OnModelCreating(modelBuilder);
|
|
|
+ }
|
|
|
+ public DbSet<LogRes> LogRes { set; get; }
|
|
|
+ }
|
|
|
+ /// <summary>
|
|
|
+ /// 基础表上下文(id为int)
|
|
|
+ /// </summary>
|
|
|
+ public class RHDWContext : DbContextBase
|
|
|
+ {
|
|
|
+ public string DbFile;
|
|
|
+ public RHDWContext() : base("DbCon") //配置使用的连接名
|
|
|
+ {
|
|
|
+ //|DataDirectory|在mvc等程序中代表了App_Data,在普通程序中代表程序根目录
|
|
|
+ this.DbFile = Database.Connection.ConnectionString.Replace("Data Source=", "").Replace("|DataDirectory|\\", "");
|
|
|
+ }
|
|
|
+
|
|
|
+ public Task<List<T>> SqlQueryAsync<T>(string sql)
|
|
|
+ {
|
|
|
+ return this.Database.SqlQuery<T>(sql).ToListAsync();
|
|
|
+ }
|
|
|
+ public Task<T> SqlQueryOneAsync<T>(string sql)
|
|
|
+ {
|
|
|
+ return this.Database.SqlQuery<T>(sql).FirstOrDefaultAsync();
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
protected override void OnModelCreating(DbModelBuilder modelBuilder)
|
|
|
{
|
|
|
this.Database.Log = msg =>
|
|
|
@@ -206,6 +266,7 @@ namespace XdCxRhDW.Repostory
|
|
|
|
|
|
public DbSet<SysSetings> SysSetings { get; set; }
|
|
|
|
|
|
+ public DbSet<TaskRunnningInfo> TaskRunnningInfos { get; set; }
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
@@ -243,8 +304,9 @@ namespace XdCxRhDW.Repostory
|
|
|
this.DbFile = dbFile;
|
|
|
}
|
|
|
|
|
|
- public string CheckTableField()
|
|
|
+ public bool IsTableFieldSync()
|
|
|
{
|
|
|
+ bool val = true;
|
|
|
var tables = this.Database.SqlQuery<string>("select name from sqlite_master where type='table' and name not like 'sqlite%'").ToList();
|
|
|
var props = this.GetType().GetProperties();
|
|
|
List<Type> entityTypes = new List<Type>();
|
|
|
@@ -260,7 +322,8 @@ namespace XdCxRhDW.Repostory
|
|
|
foreach (var table in tables)
|
|
|
{
|
|
|
var res = this.Database.SqlQuery<DbTableColumnInfo>($"PRAGMA table_info([{table}])").ToList();
|
|
|
- var entityType = entityTypes.First(p => p.Name == table);
|
|
|
+ var entityType = entityTypes.FirstOrDefault(p => p.Name == table);
|
|
|
+ if (entityType == null) continue;
|
|
|
var entityProps = entityType.GetProperties().Where(p =>
|
|
|
p.CanRead
|
|
|
&& p.CanWrite
|
|
|
@@ -268,7 +331,7 @@ namespace XdCxRhDW.Repostory
|
|
|
&& p.GetCustomAttribute<NotMappedAttribute>() == null);
|
|
|
foreach (var prop in entityProps)
|
|
|
{
|
|
|
- var find = res.Find(p => p.name == prop.Name);
|
|
|
+ var find = res.Find(p => p.name.ToLower() == prop.Name.ToLower());
|
|
|
if (find == null)
|
|
|
{
|
|
|
string typeStr = "";
|
|
|
@@ -281,7 +344,7 @@ namespace XdCxRhDW.Repostory
|
|
|
{
|
|
|
typeStr = "nvarchar";
|
|
|
}
|
|
|
- else if (type == typeof(int) || type == typeof(long))
|
|
|
+ else if (type == typeof(int) || type == typeof(long) || prop.PropertyType.IsEnum)
|
|
|
{
|
|
|
typeStr = "int";
|
|
|
}
|
|
|
@@ -293,23 +356,28 @@ namespace XdCxRhDW.Repostory
|
|
|
{
|
|
|
typeStr = "datetime";
|
|
|
}
|
|
|
- return $"{DbFile}数据库表{table}缺少{prop.Name}字段,类型={typeStr}";
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
+ bool isNullable = prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>);
|
|
|
|
|
|
- if (prop.PropertyType != typeof(string) && find.pk == 0 && !prop.PropertyType.IsGenericType && find.notnull == 0)
|
|
|
+ string updateTableSql;
|
|
|
+ if (isNullable)
|
|
|
+ updateTableSql = $"alter table {table} add column {prop.Name} {typeStr}";
|
|
|
+ else
|
|
|
{
|
|
|
- var foreignInfo = this.Database.SqlQuery<DbTableForeignKeyInfo>($"PRAGMA foreign_key_list({table})").ToList();
|
|
|
- if (!foreignInfo.Any(p => p.from == prop.Name))
|
|
|
- {
|
|
|
- return $"{DbFile}数据库表{table}中{prop.Name}字段不允许为空";
|
|
|
- }
|
|
|
+ if (typeStr == "int" || typeStr == "float")
|
|
|
+ updateTableSql = $"alter table {table} add column {prop.Name} {typeStr} not null default 0";
|
|
|
+ else if (typeStr == "nvarchar")
|
|
|
+ updateTableSql = $"alter table {table} add column {prop.Name} {typeStr} not null default ''";
|
|
|
+ else if (typeStr == "datetime")
|
|
|
+ updateTableSql = $"alter table {table} add column {prop.Name} {typeStr} not null default '{DateTime.Now:yyyy-MM-dd HH:mm:ss}'";
|
|
|
+ else
|
|
|
+ updateTableSql = $"alter table {table} add column {prop.Name} {typeStr}";
|
|
|
}
|
|
|
+ this.Database.ExecuteSqlCommand(updateTableSql);
|
|
|
+ val = false;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- return "";
|
|
|
+ return val;
|
|
|
}
|
|
|
protected override void OnModelCreating(DbModelBuilder modelBuilder)
|
|
|
{
|