I have a process in my program that uses an Entity Framework 4 EDM. The entity context object contains function imports for calling stored procedures.

The process receives a batch of data from a remote server. The batch can consist of data for any of our tables / data types (each data type is stored in its own table). The batch can also contain data for the same row multiple times. It has to handle this as a single insert (for the first occurance) and one or more updates (for each subsequent occurance). The stored procedures therefore implement an upsert operation using the INSERT ... ON EXISTING UPDATE command.

Our code basically determines which stored procedure to call and then calls it using the entity context object's method for that stored procedure. The entire batch has to be done in a single transaction, so we call context.Connection.BeginTransaction() at the beginning of the batch.

There is one data type that has millions of rows. We need to load that data as quickly as possible. I'm implementing logic to import that data type using the SABulkCopy class. This also needs to be a part of the single transaction already started. The issue is that I need to pass an SATransaction to the SABulkCopy class's constructor (there is no way to set it using properties) and I don't have an SATransaction (context.Connection.BeginTransaction()'s return type is DBTransaction, but it actually returns an EntityTransaction). I tried to cast this into an SATransaction without success.

What's the right way to get the SABulkCopy object to join the transaction?

asked 07 Sep '12, 15:17

TonyV's gravatar image

TonyV
1.2k333967
accept rate: 75%

edited 08 Sep '12, 11:14


I also posted this question on stackoverflow.com. It turns out that the EntityTransaction class has a private member called StoreTransaction where the provider-specific Transaction object is stored, in this case an SATransaction. The problem is that it's private.

There is a way to get at that private member using reflection. Unfortunately, the reflection method will not work if your code is running in a partially trusted environment.

For those interested, here is a link to a question on stackoverflow.com showing how to access the the private StoreTransaction property using reflection.

As this doesn't always work, it would be better if Microsoft exposed this property by making it public.

permanent link

answered 08 Sep '12, 11:23

TonyV's gravatar image

TonyV
1.2k333967
accept rate: 75%

edited 08 Sep '12, 11:25

Just an idea (not tested): you can create (construct) the context with an entityconnection. The EntityConnection can be created by yourself from an SAConnection. Doing so you have the SAConnection before the Entity Framework is doing all its stuff.

System.Data.Metadata.Edm.MetadataWorkspace myWorkspace =
            new System.Data.Metadata.Edm.MetadataWorkspace(new string[] { "res://*/" },
                new Assembly[] { Assembly.GetExecutingAssembly() });
EntityConnection myCon=new EntityConnection(myWorkspace,
            new iAnywhere.Data.SQLAnywhere.SAConnection(
                "...your connection string..."));

After that you should be able to do a new ObjectContext(myCon);

permanent link

answered 10 Sep '12, 07:53

Martin's gravatar image

Martin
8.6k116151237
accept rate: 14%

That's an interesting idea, but I don't see how it helps. It's not the connection that's giving me the problem; it's the transaction. On reviewing the documentation for EntityTransaction, there are no public constructors for the class. If I could have created a provider-specific transaction and got the entity context to join that transaction, that would be preferable to using reflection to obtain the value of a private field. I don't see how that can be done, though.

(10 Sep '12, 11:46) TonyV
Replies hidden

I see, so let us try: 1) For the SAConnection call CreateCommand, this will give you a SACommand joining the transaction, so you can access the underlying SATransaction through the SACommand. - or - 2) call BeginTransaction before providing your SAConnection to the ObjectContext, from the docs it seems, that in this case the Entity Framework will not create an own transaction.

(11 Sep '12, 04:05) Martin

I've tried #2 before, and it doesn't work. I get an error telling me that I have to provide a Transaction object to the Command when the connection is alread in a transaction. CreateCommand, on the other hand, I have not tried, and will give that a shot at some point.

(14 Sep '12, 10:09) TonyV

Thanks for sharing your experience

(14 Sep '12, 12:16) Martin
Your answer
toggle preview

Follow this question

By Email:

Once you sign in you will be able to subscribe for any updates here

By RSS:

Answers

Answers and Comments

Markdown Basics

  • *italic* or _italic_
  • **bold** or __bold__
  • link:[text](http://url.com/ "title")
  • image?![alt text](/path/img.jpg "title")
  • numbered list: 1. Foo 2. Bar
  • to add a line break simply add two spaces to where you would like the new line to be.
  • basic HTML tags are also supported

Question tags:

×65
×47

question asked: 07 Sep '12, 15:17

question was seen: 1,249 times

last updated: 14 Sep '12, 12:16