Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inserting large BLOB field (>500 MB) - System.OutOfMemoryException [DNET409] #410

Closed
firebird-automations opened this issue Feb 17, 2012 · 5 comments

Comments

@firebird-automations
Copy link

Submitted by: Zsák Szabolcs (zsakszabolcs)

Duplicates DNET279

I tried to insert a new record to a table. The table had an integer and a Blob field.
The size of the blob value was more than 500 MB.
An System.OutOfMemoryException exception is raised after ExecuteNonQuery.

This is the code:

        FbConnectionStringBuilder sb = new FbConnectionStringBuilder\(\);
        sb\.UserID = UserID;
        sb\.Password = Password;
        sb\.Database = Database;
        sb\.DataSource = DataSource;
        sb\.Port = Port;

        using \(FbConnection conn = new FbConnection\(sb\.ConnectionString\)\)
        \{
            conn\.Open\(\);
            using \(FbCommand comm = new FbCommand\("INSERT INTO \\"SomeTable\\" \(\\"Id\\",\\"Image\\"\) VALUES \(@id,@blob\)", conn\)\)
            \{
                FbParameter p1 = comm\.Parameters\.Add\("@blob", FbDbType\.Binary\);
                p1\.Value = System\.IO\.File\.ReadAllBytes\(BIGFILE\);
                p1\.Direction = ParameterDirection\.Input;

                FbParameter p2 = comm\.Parameters\.Add\("@id", FbDbType\.Integer\);
                p2\.Value = 1;
                p2\.Direction = ParameterDirection\.Input;

                comm\.ExecuteNonQuery\(\);
            \}
            conn\.Close\(\);
        \}

The memory consumption is big because of the InternalValue get-property of the FbParameter class.
This get-property makes a copy from Blob value, and it's called many times. I think the objectcopy isn't necessary always!

@firebird-automations
Copy link
Author

Commented by: @mrotteveel

Isn't it possible to stream the blob with the .NET provider? If you stream there is no need for intermediate storage on the client side.

@firebird-automations
Copy link
Author

Commented by: @cincuranet

Subset of DNET279 .

@firebird-automations
Copy link
Author

Modified by: @cincuranet

status: Open [ 1 ] => Closed [ 6 ]

resolution: Duplicate [ 3 ]

@firebird-automations
Copy link
Author

Modified by: @cincuranet

Link: This issue duplicates DNET279 [ DNET279 ]

@firebird-automations
Copy link
Author

Commented by: Zsák Szabolcs (zsakszabolcs)

It can be a subset of DNET279, but there is a very fast solution to repair this. You can change the usage of the InternalValue property to the simple Value property in the if conditions. I tried this with success.

For example:
FbCommand.cs:1052
if (this.Parameters[index].InternalValue == DBNull.Value || this.Parameters[index].InternalValue == null)
to
if (this.Parameters[index].Value == DBNull.Value || this.Parameters[index].Value == null)

FbCommand.cs:1072
blob.Write((byte[])this.Parameters[index].InternalValue);
FbCommand.cs:1080
if (this.Parameters[index].InternalValue is byte[])
FbCommand.cs:1081
blob.Write((byte[])this.Parameters[index].InternalValue);
FbCommand.cs:1083
blob.Write((string)this.Parameters[index].InternalValue);
FbCommand.cs:1104
this.statement.Parameters[i].ArrayHandle.Write((System.Array)this.Parameters[index].InternalValue);
FbCommand.cs:1110
if (!(this.Parameters[index].InternalValue is Guid) &&
!(this.Parameters[index].InternalValue is byte[]))
FbCommand.cs:1401
TraceHelper.Trace(TraceEventType.Information, "Name:{0}\tType:{1}\tUsed Value:{2}", item.ParameterName, item.FbDbType, (!IsNullParameterValue(item.InternalValue) ? item.InternalValue : "<null>"));

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants