|
|
|
|
@@ -1,4 +1,5 @@
|
|
|
|
|
using FreeSql.DataAnnotations;
|
|
|
|
|
using FreeSql.Extensions.ZeroEntity.Models;
|
|
|
|
|
using FreeSql.Internal;
|
|
|
|
|
using FreeSql.Internal.CommonProvider;
|
|
|
|
|
using FreeSql.Internal.Model;
|
|
|
|
|
@@ -64,23 +65,58 @@ ManyToMany 级联删除中间表(注意不删除外部根)
|
|
|
|
|
internal DbTransaction _transaction;
|
|
|
|
|
internal int _commandTimeout;
|
|
|
|
|
internal List<ZeroTableInfo> _tables;
|
|
|
|
|
public ZeroDbContext(IFreeSql orm, TableDescriptor[] schemas)
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 创建新的ZeroDbCotext实例
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="orm">IfreeSql 对象</param>
|
|
|
|
|
/// <param name="schemas">动态表结构描述</param>
|
|
|
|
|
/// <param name="syncStructure">是否强制同步表结构</param>
|
|
|
|
|
/// <exception cref="SchemaValidationResult"> Schema 未验证通过时抛出验证异常</exception>
|
|
|
|
|
public ZeroDbContext(IFreeSql orm, TableDescriptor[] schemas, bool syncStructure = false)
|
|
|
|
|
{
|
|
|
|
|
_orm = orm;
|
|
|
|
|
_tables = ValidateSchemaToInfo(orm, schemas);
|
|
|
|
|
if (orm.CodeFirst.IsAutoSyncStructure)
|
|
|
|
|
_tables = ValidateSchemaToInfoInternal(orm, schemas);
|
|
|
|
|
if (syncStructure || orm.CodeFirst.IsAutoSyncStructure)
|
|
|
|
|
{
|
|
|
|
|
foreach (var table in _tables)
|
|
|
|
|
orm.CodeFirst.SyncStructure(table, table.DbName, false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public SchemaValidationResult ValidateSchema(IEnumerable<TableDescriptor> schemas)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
ValidateSchemaToInfoInternal(_orm, schemas);
|
|
|
|
|
}
|
|
|
|
|
catch (SchemaValidationException ex)
|
|
|
|
|
{
|
|
|
|
|
return new SchemaValidationResult(ex.Message);
|
|
|
|
|
}
|
|
|
|
|
return SchemaValidationResult.SuccessedResult;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public TableInfo GetTableInfo(string name) => _tables.Where(a => a.CsName == name).FirstOrDefault();
|
|
|
|
|
public void SyncStructure(string name)
|
|
|
|
|
|
|
|
|
|
public void SyncStructure()
|
|
|
|
|
{
|
|
|
|
|
foreach (var table in _tables)
|
|
|
|
|
_orm.CodeFirst.SyncStructure(table, table.DbName, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 同步指定表结构
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="name"></param>
|
|
|
|
|
public void SyncTableStructure(string name)
|
|
|
|
|
{
|
|
|
|
|
var table = GetTableInfo(name);
|
|
|
|
|
_orm.CodeFirst.SyncStructure(table, table.DbName, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static List<ZeroTableInfo> ValidateSchemaToInfo(IFreeSql orm, IEnumerable<TableDescriptor> schemas)
|
|
|
|
|
|
|
|
|
|
static List<ZeroTableInfo> ValidateSchemaToInfoInternal(IFreeSql orm, IEnumerable<TableDescriptor> schemas)
|
|
|
|
|
{
|
|
|
|
|
var common = (orm.Ado as AdoProvider)._util;
|
|
|
|
|
var tables = new List<ZeroTableInfo>();
|
|
|
|
|
@@ -141,7 +177,8 @@ ManyToMany 级联删除中间表(注意不删除外部根)
|
|
|
|
|
nav.NavigateKey = dtdnav.Name;
|
|
|
|
|
nav.Table = tab;
|
|
|
|
|
nav.RefTable = tables.Where(a => a.CsName == dtdnav.RelTable).FirstOrDefault();
|
|
|
|
|
if (nav.RefTable == null) throw new Exception($"{error}未定义“{dtdnav.RelTable}”");
|
|
|
|
|
|
|
|
|
|
if (nav.RefTable == null) throw new SchemaValidationException($"{error}未定义“{dtdnav.RelTable}”");
|
|
|
|
|
|
|
|
|
|
switch (dtdnav.Type)
|
|
|
|
|
{
|
|
|
|
|
@@ -173,22 +210,22 @@ ManyToMany 级联删除中间表(注意不删除外部根)
|
|
|
|
|
nav.RefType = TableRefType.ManyToMany;
|
|
|
|
|
var midtab = tables.Where(a => a.CsName == dtdnav.ManyToMany).FirstOrDefault();
|
|
|
|
|
nav.RefMiddleTable = midtab;
|
|
|
|
|
if (nav.RefMiddleTable == null) throw new Exception($"{error}ManyToMany未定义“{dtdnav.ManyToMany}”");
|
|
|
|
|
if (nav.RefMiddleTable == null) throw new SchemaValidationException($"{error}ManyToMany未定义“{dtdnav.ManyToMany}”");
|
|
|
|
|
var midtabRaw = schemas.Where(a => a.Name == midtab.CsName).FirstOrDefault();
|
|
|
|
|
var midTabNav1 = midtabRaw.Navigates.Where(a => a.Type == TableDescriptor.NavigateType.ManyToOne && a.RelTable == nav.Table.CsName).FirstOrDefault();
|
|
|
|
|
if (midTabNav1 == null) throw new Exception($"{error}ManyToMany中间表“{dtdnav.ManyToMany}”没有与表“{nav.Table.CsName}”形成 ManyToOne 关联");
|
|
|
|
|
if (midTabNav1 == null) throw new SchemaValidationException($"{error}ManyToMany中间表“{dtdnav.ManyToMany}”没有与表“{nav.Table.CsName}”形成 ManyToOne 关联");
|
|
|
|
|
var midTabNav1Columns = midTabNav1.Bind.Split(',')
|
|
|
|
|
.Select(a => midtab.ColumnsByCs.TryGetValue(a.Trim(), out var refcol) ? refcol.CsName : "")
|
|
|
|
|
.Where(a => string.IsNullOrWhiteSpace(a) == false).ToArray();
|
|
|
|
|
var midTabNav2 = midtabRaw.Navigates.Where(a => a.Type == TableDescriptor.NavigateType.ManyToOne && a.RelTable == nav.RefTable.CsName).FirstOrDefault();
|
|
|
|
|
if (midTabNav2 == null) throw new Exception($"{error}ManyToMany中间表“{dtdnav.ManyToMany}”没有与表“{nav.RefTable.CsName}”形成 ManyToOne 关联");
|
|
|
|
|
if (midTabNav2 == null) throw new SchemaValidationException($"{error}ManyToMany中间表“{dtdnav.ManyToMany}”没有与表“{nav.RefTable.CsName}”形成 ManyToOne 关联");
|
|
|
|
|
var midTabNav2Columns = midTabNav2.Bind.Split(',')
|
|
|
|
|
.Select(a => midtab.ColumnsByCs.TryGetValue(a.Trim(), out var refcol) ? refcol.CsName : "")
|
|
|
|
|
.Where(a => string.IsNullOrWhiteSpace(a) == false).ToArray();
|
|
|
|
|
if (midTabNav1Columns.Length != nav.Table.Primarys.Length) throw new Exception($"{error}ManyToMany中间表“{dtdnav.ManyToMany}”关联字段的数目不相等");
|
|
|
|
|
if (midTabNav1Columns.Where((a, idx) => midtab.ColumnsByCs[a].CsType != nav.Table.Primarys[idx].CsType).Any()) throw new Exception($"{error}ManyToMany中间表“{dtdnav.ManyToMany}”关联字段的类型不相等");
|
|
|
|
|
if (midTabNav2Columns.Length != nav.RefTable.Primarys.Length) throw new Exception($"{error}ManyToMany中间表“{dtdnav.ManyToMany}”与表“{nav.RefTable.CsName}”关联字段的数目不相等");
|
|
|
|
|
if (midTabNav2Columns.Where((a, idx) => midtab.ColumnsByCs[a].CsType != nav.RefTable.Primarys[idx].CsType).Any()) throw new Exception($"{error}ManyToMany中间表“{dtdnav.ManyToMany}”与表“{nav.RefTable.CsName}”关联字段的类型不相等");
|
|
|
|
|
if (midTabNav1Columns.Length != nav.Table.Primarys.Length) throw new SchemaValidationException($"{error}ManyToMany中间表“{dtdnav.ManyToMany}”关联字段的数目不相等");
|
|
|
|
|
if (midTabNav1Columns.Where((a, idx) => midtab.ColumnsByCs[a].CsType != nav.Table.Primarys[idx].CsType).Any()) throw new SchemaValidationException($"{error}ManyToMany中间表“{dtdnav.ManyToMany}”关联字段的类型不相等");
|
|
|
|
|
if (midTabNav2Columns.Length != nav.RefTable.Primarys.Length) throw new SchemaValidationException($"{error}ManyToMany中间表“{dtdnav.ManyToMany}”与表“{nav.RefTable.CsName}”关联字段的数目不相等");
|
|
|
|
|
if (midTabNav2Columns.Where((a, idx) => midtab.ColumnsByCs[a].CsType != nav.RefTable.Primarys[idx].CsType).Any()) throw new SchemaValidationException($"{error}ManyToMany中间表“{dtdnav.ManyToMany}”与表“{nav.RefTable.CsName}”关联字段的类型不相等");
|
|
|
|
|
nav.Columns.AddRange(nav.Table.Primarys.Select(a => a.CsName));
|
|
|
|
|
nav.MiddleColumns.AddRange(midTabNav1Columns);
|
|
|
|
|
nav.MiddleColumns.AddRange(midTabNav2Columns);
|
|
|
|
|
@@ -200,8 +237,8 @@ ManyToMany 级联删除中间表(注意不删除外部根)
|
|
|
|
|
case TableDescriptor.NavigateType.OneToOne:
|
|
|
|
|
case TableDescriptor.NavigateType.ManyToOne:
|
|
|
|
|
case TableDescriptor.NavigateType.OneToMany:
|
|
|
|
|
if (nav.Columns.Any() == false || nav.Columns.Count != nav.RefColumns.Count) throw new Exception($"{error}与表“{dtdnav.RelTable}”关联字段的数目不相等");
|
|
|
|
|
if (nav.Columns.Where((a, idx) => nav.Table.ColumnsByCs[a].CsType != nav.RefTable.ColumnsByCs[nav.RefColumns[idx]].CsType).Any()) throw new Exception($"{error}与表“{dtdnav.RelTable}”关联字段的类型不匹配");
|
|
|
|
|
if (nav.Columns.Any() == false || nav.Columns.Count != nav.RefColumns.Count) throw new SchemaValidationException($"{error}与表“{dtdnav.RelTable}”关联字段的数目不相等");
|
|
|
|
|
if (nav.Columns.Where((a, idx) => nav.Table.ColumnsByCs[a].CsType != nav.RefTable.ColumnsByCs[nav.RefColumns[idx]].CsType).Any()) throw new SchemaValidationException($"{error}与表“{dtdnav.RelTable}”关联字段的类型不匹配");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
tab.Navigates.Add(dtdnav.Name, nav);
|
|
|
|
|
|