ralmsdeveloper / EntityFrameworkCore.FirebirdSQL

FirebirdSQL database provider for Entity Framework Core.
Other
44 stars 26 forks source link

block size exceeds implementation restriction #29

Closed jojastahl closed 6 years ago

jojastahl commented 6 years ago

The issue

Saving updates to entities raises exception

Steps to reproduce

No reproducing example solution created yet.

Error details

If you are seeing an exception, include the full exceptions details (message and stack trace).

Exception message:
Microsoft.EntityFrameworkCore.DbUpdateException: An error occurred while updating the entries. See the inner exception for details. ---> FirebirdSql.Data.FirebirdClient.FbException: Dynamic SQL Error
SQL error code = -204
Implementation limit exceeded
block size exceeds implementation restriction ---> FirebirdSql.Data.Common.IscException: Dynamic SQL Error
SQL error code = -204
Implementation limit exceeded
block size exceeds implementation restriction
   bei FirebirdSql.Data.Client.Managed.Version10.GdsDatabase.ProcessResponse(IResponse response)
   bei FirebirdSql.Data.Client.Managed.Version10.GdsDatabase.ReadResponse()
   bei FirebirdSql.Data.Client.Managed.Version10.GdsDatabase.ReadGenericResponse()
   bei FirebirdSql.Data.Client.Managed.Version11.GdsStatement.Prepare(String commandText)
   bei FirebirdSql.Data.FirebirdClient.FbCommand.Prepare(Boolean returnsSet)
   bei FirebirdSql.Data.FirebirdClient.FbCommand.ExecuteCommand(CommandBehavior behavior, Boolean returnsSet)
   bei FirebirdSql.Data.FirebirdClient.FbCommand.ExecuteReader(CommandBehavior behavior)
   --- Ende der internen Ausnahmestapelüberwachung ---
   bei FirebirdSql.Data.FirebirdClient.FbCommand.ExecuteReader(CommandBehavior behavior)
   bei FirebirdSql.Data.FirebirdClient.FbCommand.ExecuteDbDataReader(CommandBehavior behavior)
   bei System.Data.Common.DbCommand.ExecuteDbDataReaderAsync(CommandBehavior behavior, CancellationToken cancellationToken)
--- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde ---
   bei System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   bei System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
   bei Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.<ExecuteAsync>d__17.MoveNext()
--- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde ---
   bei System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   bei Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.<ExecuteAsync>d__32.MoveNext()
   --- Ende der internen Ausnahmestapelüberwachung ---
   bei EntityFrameworkCore.FirebirdSql.Update.Internal.FbBatchExecutor.<ExecuteAsync>d__1.MoveNext()
--- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde ---
   bei System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   bei Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.<SaveChangesAsync>d__61.MoveNext()
--- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde ---
   bei System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   bei Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.<SaveChangesAsync>d__59.MoveNext()
--- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde ---
   bei System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   bei Microsoft.EntityFrameworkCore.DbContext.<SaveChangesAsync>d__48.MoveNext()
--- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde ---
   bei System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   bei System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   bei Prosys2.Automat.Planning.UpdateTasksFromAutoObjectJob.<RunAsync>d__12.MoveNext()
--- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde ---
   bei System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   bei System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   bei Prosys2.Automat.Planning.PlanningEngine.<RunJob>d__17.MoveNext()

Further technical details

Firebird version: 2.5 EntityFrameworkCore.FirebirdSql version: 2.0.11 FirebirdSql.Data.FirebirdClient: 5.12.0.0

Other details about my project setup:

jojastahl commented 6 years ago

See http://www.firebirdfaq.org/faq299/ for info when this can happen.

jojastahl commented 6 years ago

The SQL Command to be executed:

EXECUTE BLOCK ( 
p0  VARCHAR(4000)=@p0,p1  SMALLINT=@p1,p2  INTEGER=@p2,p3  INTEGER=@p3,p4  VARCHAR(4000)=@p4,p5  TIMESTAMP=@p5,p6  INTEGER=@p6,p7  VARCHAR(256)=@p7,p8  SMALLINT=@p8,p9  SMALLINT=@p9,p10  VARCHAR(4000)=@p10,p11  INTEGER=@p11,p12  VARCHAR(4000)=@p12,p13  VARCHAR(4000)=@p13,p14  SMALLINT=@p14,p15  INTEGER=@p15,p16  INTEGER=@p16,p17  VARCHAR(4000)=@p17,p18  TIMESTAMP=@p18,p19  INTEGER=@p19,p20  VARCHAR(256)=@p20,p21  SMALLINT=@p21,p22  SMALLINT=@p22,p23  VARCHAR(4000)=@p23,p24  INTEGER=@p24,p25  VARCHAR(4000)=@p25,p26  VARCHAR(4000)=@p26,p27  SMALLINT=@p27,p28  INTEGER=@p28,p29  INTEGER=@p29,p30  VARCHAR(4000)=@p30,p31  TIMESTAMP=@p31,p32  INTEGER=@p32,p33  VARCHAR(256)=@p33,p34  SMALLINT=@p34,p35  SMALLINT=@p35,p36  VARCHAR(4000)=@p36,p37  INTEGER=@p37,p38  VARCHAR(4000)=@p38,p39  VARCHAR(4000)=@p39,p40  SMALLINT=@p40,p41  INTEGER=@p41,p42  INTEGER=@p42,p43  VARCHAR(4000)=@p43,p44  TIMESTAMP=@p44,p45  INTEGER=@p45,p46  VARCHAR(256)=@p46,p47  SMALLINT=@p47,p48  SMALLINT=@p48,p49  VARCHAR(4000)=@p49,p50  INTEGER=@p50,p51  VARCHAR(4000)=@p51,p52  VARCHAR(4000)=@p52,p53  SMALLINT=@p53,p54  INTEGER=@p54,p55  INTEGER=@p55,p56  VARCHAR(4000)=@p56,p57  TIMESTAMP=@p57,p58  INTEGER=@p58,p59  VARCHAR(256)=@p59,p60  SMALLINT=@p60,p61  SMALLINT=@p61,p62  VARCHAR(4000)=@p62,p63  INTEGER=@p63,p64  VARCHAR(4000)=@p64) 
 RETURNS (TASK_ID INTEGER) AS BEGIN

INSERT INTO "PLAN_TASK" ("BEZ", "FINISHED", "DURATION", "PREV_TASK_ON_RES", "RES_ID", "START_TS", "START_TOLERANZ", "OBJID", "STARTED", "SCHRITT", "SYNC_KEY", "TASK_TYPE", "DYNAMIC_PROPS")
VALUES (:p0, :p1, :p2, :p3, :p4, :p5, :p6, :p7, :p8, :p9, :p10, :p11, :p12) RETURNING "TASK_ID" INTO :TASK_ID;
SUSPEND;
INSERT INTO "PLAN_TASK" ("BEZ", "FINISHED", "DURATION", "PREV_TASK_ON_RES", "RES_ID", "START_TS", "START_TOLERANZ", "OBJID", "STARTED", "SCHRITT", "SYNC_KEY", "TASK_TYPE", "DYNAMIC_PROPS")
VALUES (:p13, :p14, :p15, :p16, :p17, :p18, :p19, :p20, :p21, :p22, :p23, :p24, :p25) RETURNING "TASK_ID" INTO :TASK_ID;
SUSPEND;
INSERT INTO "PLAN_TASK" ("BEZ", "FINISHED", "DURATION", "PREV_TASK_ON_RES", "RES_ID", "START_TS", "START_TOLERANZ", "OBJID", "STARTED", "SCHRITT", "SYNC_KEY", "TASK_TYPE", "DYNAMIC_PROPS")
VALUES (:p26, :p27, :p28, :p29, :p30, :p31, :p32, :p33, :p34, :p35, :p36, :p37, :p38) RETURNING "TASK_ID" INTO :TASK_ID;
SUSPEND;
INSERT INTO "PLAN_TASK" ("BEZ", "FINISHED", "DURATION", "PREV_TASK_ON_RES", "RES_ID", "START_TS", "START_TOLERANZ", "OBJID", "STARTED", "SCHRITT", "SYNC_KEY", "TASK_TYPE", "DYNAMIC_PROPS")
VALUES (:p39, :p40, :p41, :p42, :p43, :p44, :p45, :p46, :p47, :p48, :p49, :p50, :p51) RETURNING "TASK_ID" INTO :TASK_ID;
SUSPEND;
INSERT INTO "PLAN_TASK" ("BEZ", "FINISHED", "DURATION", "PREV_TASK_ON_RES", "RES_ID", "START_TS", "START_TOLERANZ", "OBJID", "STARTED", "SCHRITT", "SYNC_KEY", "TASK_TYPE", "DYNAMIC_PROPS")
VALUES (:p52, :p53, :p54, :p55, :p56, :p57, :p58, :p59, :p60, :p61, :p62, :p63, :p64) RETURNING "TASK_ID" INTO :TASK_ID;
SUSPEND;
END;

The parameters used:

    [0]: "@p0   FbDbType=VarChar   Size=4000"
    [1]: "@p1   FbDbType=SmallInt   Size=0"
    [2]: "@p2   FbDbType=Integer   Size=0"
    [3]: "@p3   FbDbType=Integer   Size=0"
    [4]: "@p4   FbDbType=VarChar   Size=4000"
    [5]: "@p5   FbDbType=TimeStamp   Size=0"
    [6]: "@p6   FbDbType=Integer   Size=0"
    [7]: "@p7   FbDbType=VarChar   Size=256"
    [8]: "@p8   FbDbType=SmallInt   Size=0"
    [9]: "@p9   FbDbType=SmallInt   Size=0"
    [10]: "@p10   FbDbType=VarChar   Size=4000"
    [11]: "@p11   FbDbType=Integer   Size=0"
    [12]: "@p12   FbDbType=VarChar   Size=4000"
    [13]: "@p13   FbDbType=VarChar   Size=4000"
    [14]: "@p14   FbDbType=SmallInt   Size=0"
    [15]: "@p15   FbDbType=Integer   Size=0"
    [16]: "@p16   FbDbType=Integer   Size=0"
    [17]: "@p17   FbDbType=VarChar   Size=4000"
    [18]: "@p18   FbDbType=TimeStamp   Size=0"
    [19]: "@p19   FbDbType=Integer   Size=0"
    [20]: "@p20   FbDbType=VarChar   Size=256"
    [21]: "@p21   FbDbType=SmallInt   Size=0"
    [22]: "@p22   FbDbType=SmallInt   Size=0"
    [23]: "@p23   FbDbType=VarChar   Size=4000"
    [24]: "@p24   FbDbType=Integer   Size=0"
    [25]: "@p25   FbDbType=VarChar   Size=4000"
    [26]: "@p26   FbDbType=VarChar   Size=4000"
    [27]: "@p27   FbDbType=SmallInt   Size=0"
    [28]: "@p28   FbDbType=Integer   Size=0"
    [29]: "@p29   FbDbType=Integer   Size=0"
    [30]: "@p30   FbDbType=VarChar   Size=4000"
    [31]: "@p31   FbDbType=TimeStamp   Size=0"
    [32]: "@p32   FbDbType=Integer   Size=0"
    [33]: "@p33   FbDbType=VarChar   Size=256"
    [34]: "@p34   FbDbType=SmallInt   Size=0"
    [35]: "@p35   FbDbType=SmallInt   Size=0"
    [36]: "@p36   FbDbType=VarChar   Size=4000"
    [37]: "@p37   FbDbType=Integer   Size=0"
    [38]: "@p38   FbDbType=VarChar   Size=4000"
    [39]: "@p39   FbDbType=VarChar   Size=4000"
    [40]: "@p40   FbDbType=SmallInt   Size=0"
    [41]: "@p41   FbDbType=Integer   Size=0"
    [42]: "@p42   FbDbType=Integer   Size=0"
    [43]: "@p43   FbDbType=VarChar   Size=4000"
    [44]: "@p44   FbDbType=TimeStamp   Size=0"
    [45]: "@p45   FbDbType=Integer   Size=0"
    [46]: "@p46   FbDbType=VarChar   Size=256"
    [47]: "@p47   FbDbType=SmallInt   Size=0"
    [48]: "@p48   FbDbType=SmallInt   Size=0"
    [49]: "@p49   FbDbType=VarChar   Size=4000"
    [50]: "@p50   FbDbType=Integer   Size=0"
    [51]: "@p51   FbDbType=VarChar   Size=4000"
    [52]: "@p52   FbDbType=VarChar   Size=4000"
    [53]: "@p53   FbDbType=SmallInt   Size=0"
    [54]: "@p54   FbDbType=Integer   Size=0"
    [55]: "@p55   FbDbType=Integer   Size=0"
    [56]: "@p56   FbDbType=VarChar   Size=4000"
    [57]: "@p57   FbDbType=TimeStamp   Size=0"
    [58]: "@p58   FbDbType=Integer   Size=0"
    [59]: "@p59   FbDbType=VarChar   Size=256"
    [60]: "@p60   FbDbType=SmallInt   Size=0"
    [61]: "@p61   FbDbType=SmallInt   Size=0"
    [62]: "@p62   FbDbType=VarChar   Size=4000"
    [63]: "@p63   FbDbType=Integer   Size=0"
    [64]: "@p64   FbDbType=VarChar   Size=4000"
ralmsdeveloper commented 6 years ago

Thanks for reporting, I'll review for the next two days!

Could you test in version 2.1-RC1 if this is working? https://www.nuget.org/packages/EntityFrameworkCore.FirebirdSQL/2.1.0-rc1-final

jojastahl commented 6 years ago

I added a Property().HasMaxLength() for every string field now, and this works around the problem. So I think that the many parameters of size 4000 sum up to more than the implementation limit. Perhaps this limit is 64K, like the row size mentioned in point 2 here http://www.firebirdfaq.org/faq299/ ?

But if this really is the problem, then shouldn't EF Core Firebird library limit its insert statements so that parameters don't sum up to more than 64K, and instead split in multiple inserts?

ralmsdeveloper commented 6 years ago

Yes that makes sense, you can upload your project for me to reproduce on it. My time is short.

I would avoid writing a few bits :)