If can,
1.1 More than two DBContext(same or not same database, such as MS Sql Server, Oracle,Sqlite, etc) can using in a TransactionScope ?
1.2 Is there a example for using Sqlite with TransactionScope ?
2. In ASP.net enviroment, the best practice is to keep DBContext as static or get a new instance on each web quest or per session ?
3. Multi back end in a rlinq will come or not ?
28 Answers, 1 is accepted
As for number 2, it is best practice to use the "one-thread-one-context" approach. That is, creating a new Context for each request that comes in. In the knowledge base there is some examples of how to do this. In general there are two approaches of doing this... either have a common master page for all your other pages exposing the created Context or using a ContextFactory.
Both methods are equal, in that they create a Context and store it for retrieval during the lifetime of the request, for example in the HttpContext.Items object under a predefined key
As for your other questions OpenAccess has support for the System.Transactions so you can have multiple datasources enlisting in the same transaction...
Is that to say TransactionScope is not supported ?
No, in the System.Transactions namespace you have the TransactionScope class... Here's a link to the docs (of OA Classic) on how to use TransactionScope as TransactionProvider instead of the default OpenAccess provider.
TransactionScope provider
Regards
Henrik
Unfortunately as Henrik suggested it is not possible to use TransactionProvider with our new API. Underneath each context is a transaction that is managed by the contexts' public api. If you need to envelop several contexts into one logical transaction you will have to come up with your own solution. Please don't hesitate to contact us if you require more information.
Could you give us a bit more insight on what you are trying to achieve and why you need to have two database operations enlisted in the same transaction. Is that the only solution to your issue?
As for you last question - yes, multiple backend support is on our roadmap with high priority but I am not able to provide an exact date.
All the best,
Nikola
the Telerik team
Thank you for being the most amazing .NET community! Your unfailing support is what helps us charge forward! We'd appreciate your vote for Telerik in this year's SQL Server Community Awards. We are competing in TWO categories and every vote counts! VOTE for Telerik NOW >>
It's regret that OpenAccess's new api(Domain model) does't support across database transactions directly now.
Sorry for the confusion. You can use TransactionScope around several context instances. OpenAccess looks for a running system transaction if you do the first write operation in the context. Based on that the OpenAccess or the system.transaction is used.
Regards,
Jan Blessenohl
the Telerik team
Thank you for being the most amazing .NET community! Your unfailing support is what helps us charge forward! We'd appreciate your vote for Telerik in this year's SQL Server Community Awards. We are competing in TWO categories and every vote counts! VOTE for Telerik NOW >>
Thanks for elaborating.
Just to get things clear:
The methods of starting and committing a "System.Transactions" transaction is still as pointed out in the classic approach linked to in an earlier reply?
Or does the selecting of "transaction provider" happen behind the scenes of the scope, based on what transaction provider transaction is started first... if it is OpenAccess->OpenAccess is used.... if a "System.Transactions" transaction is running->TransactionScope is used`?
Regards
Henrik
You can have the context or the txn generation outside, important is the first change that you trigger. This code works fine and nothing is stored if you do not call SaveChanges or Complete.
using
(EntitiesModel ctx =
new
EntitiesModel())
{
using
(var txn =
new
TransactionScope())
{
ctx.Add(
new
Person());
ctx.SaveChanges();
txn.Complete();
}
int
i = ctx.GetAll<Person>().Count();
}
Greetings,
Jan Blessenohl
the Telerik team
Thank you for being the most amazing .NET community! Your unfailing support is what helps us charge forward! We'd appreciate your vote for Telerik in this year's SQL Server Community Awards. We are competing in TWO categories and every vote counts! VOTE for Telerik NOW >>
Thanks for elaborating.
It works like in the classic approach then - as far as I can tell.
Only you have to watch out for doing updates before you actually instantiate the TransactionScope... If you want updates to participate in the TransactionScope transaction you have to put them in between the using statement scope (as per your example).
/Henrik
Yes, that is what you are usually doing.
Best wishes,
Jan Blessenohl
the Telerik team
Thank you for being the most amazing .NET community! Your unfailing support is what helps us charge forward! We'd appreciate your vote for Telerik in this year's SQL Server Community Awards. We are competing in TWO categories and every vote counts! VOTE for Telerik NOW >>
Only context.SaveChanges() can determine whether data updated will be persisted.
Do you say that you are using my code and it does not matter if you call txn.complete, the changes are in the database?
All the best,
Jan Blessenohl
the Telerik team
Thank you for being the most amazing .NET community! Your unfailing support is what helps us charge forward! We'd appreciate your vote for Telerik in this year's SQL Server Community Awards. We are competing in TWO categories and every vote counts! VOTE for Telerik NOW >>
That's why I ask if OA support TransactionScope.
Let me rephrase,
The next two snippets should not store anything:
using
(EntitiesModel ctx =
new
EntitiesModel())
{
using
(var txn =
new
TransactionScope())
{
ctx.Add(
new
Person());
ctx.SaveChanges();
//txn.Complete();
}
int
i = ctx.GetAll<Person>().Count();
}
using
(EntitiesModel ctx =
new
EntitiesModel())
{
using
(var txn =
new
TransactionScope())
{
ctx.Add(
new
Person());
//ctx.SaveChanges();
txn.Complete();
}
int
i = ctx.GetAll<Person>().Count();
}
Only if you call both, something will be stored:
using
(EntitiesModel ctx =
new
EntitiesModel())
{
using
(var txn =
new
TransactionScope())
{
ctx.Add(
new
Person());
ctx.SaveChanges();
txn.Complete();
}
int
i = ctx.GetAll<Person>().Count();
}
Both calls are necessary because the context changes are pushed down to the server during the SaveChanges() call, but the TransactionScope keeps the SQLite transaction running until the closing bracket. You can even call several times SaveChanges() on the scope before closing the transaction bracket.
Greetings,
Jan Blessenohl
the Telerik team
Thank you for being the most amazing .NET community! Your unfailing support is what helps us charge forward! We'd appreciate your vote for Telerik in this year's SQL Server Community Awards. We are competing in TWO categories and every vote counts! VOTE for Telerik NOW >>
There is even no txn.Complete(), but you can see the ParentID of node(ID is 'bb399da7-5a54-48c1-b18e-04d6471d3e9a') change from '8a205e13-476d-4cb0-8be7-2ccfcc7718f4' to 'a092fa8a-07b0-499a-ba90-5e416b75d005'.
In your code you are using Flush(). Flush does not work together with TransactionScope. Please remove the Flush call and it will work.
Kind regards,
Jan Blessenohl
the Telerik team
Thank you for being the most amazing .NET community! Your unfailing support is what helps us charge forward! We'd appreciate your vote for Telerik in this year's SQL Server Community Awards. We are competing in TWO categories and every vote counts! VOTE for Telerik NOW >>
But as described in Support Ticket 459049, without ctx.Flush(), I can't get soft commit.
It seem that when linq in OA query data from database, some time not using 1st cache, without soft commit, the data retrieved will not keep consist with domain model, that may has fatal error.
Similar needs:
http://www.telerik.com/community/forums/orm/development/transaction-handling.aspx
http://www.telerik.com/community/forums/orm/development/transaction-management.aspx
I am sorry, but at the moment you have to choose between using flush without transaction scope or not using flush but with transaction scope.
Greetings,
Jan Blessenohl
the Telerik team
Thank you for being the most amazing .NET community! Your unfailing support is what helps us charge forward! We'd appreciate your vote for Telerik in this year's SQL Server Community Awards. We are competing in TWO categories and every vote counts! VOTE for Telerik NOW >>
I have added it to the list. I will try to get it done for the next major release.
Kind regards,
Jan Blessenohl
the Telerik team
Thank you for being the most amazing .NET community! Your unfailing support is what helps us charge forward! We'd appreciate your vote for Telerik in this year's SQL Server Community Awards. We are competing in TWO categories and every vote counts! VOTE for Telerik NOW >>
Major means Q3.
Greetings,
Jan Blessenohl
the Telerik team
Thank you for being the most amazing .NET community! Your unfailing support is what helps us charge forward! We'd appreciate your vote for Telerik in this year's SQL Server Community Awards. We are competing in TWO categories and every vote counts! VOTE for Telerik NOW >>
The Flush will work now together with System.Transactions. Please try the Q3 2011 version.
Kind regards,
Jan Blessenohl
the Telerik team
NEW and UPDATED OpenAccess ORM Resources. Check them out!
But if doesn't call context.SaveChanges and just call ts.Complete, OA will throw a TransactionAbortException.
Why should Flush() call SaveChanges? You still can decide to roll back and there can also be additonal changes between the Flush and SaveChanges() call. Flush just means we send everything to the server using the enlisted transaction, you still have to call SaveChanges() to not let us rollback everything.
Greetings,
Jan Blessenohl
the Telerik team
NEW and UPDATED OpenAccess ORM Resources. Check them out!
In fact, I mean if not calling context.SaveChanges() in a TransactionScope(ts),just calling ts.Complete can cause the exception.
Using(var ts = new TransactionScope(...
Using(var context = new FrameworkContext(...
{
//do some operation
//context.SaveChanges(); //If comment this line, a exception thrown
ts.Complete();
}
Because we use late enlistment, it is necessary to call both. We already had this discussion, can you please look through the ticket again?
Jan Blessenohl
the Telerik team
Q3’11 of Telerik OpenAccess ORM is available for download. Register for the What's New in Data Tools webinar to see what's new and get a chance to WIN A FREE LICENSE!
Thank you and your team.