@ -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 SchemaValidation Exception( $"{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 SchemaValidation Exception( $"{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 SchemaValidation Exception( $"{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 SchemaValidation Exception( $"{error}ManyToMany中间表“{dtdnav.ManyToMany}”关联字段的数目不相等" ) ;
if ( midTabNav1Columns . Where ( ( a , idx ) = > midtab . ColumnsByCs [ a ] . CsType ! = nav . Table . Primarys [ idx ] . CsType ) . Any ( ) ) throw new SchemaValidation Exception( $"{error}ManyToMany中间表“{dtdnav.ManyToMany}”关联字段的类型不相等" ) ;
if ( midTabNav2Columns . Length ! = nav . RefTable . Primarys . Length ) throw new SchemaValidation 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 SchemaValidation Exception( $"{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 SchemaValidation 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 SchemaValidation Exception( $"{error}与表“{dtdnav.RelTable}”关联字段的类型不匹配" ) ;
break ;
}
tab . Navigates . Add ( dtdnav . Name , nav ) ;