Hi! I have an instance of EntitySetBase class and want to get its count. The corresponding property throws an exception: "Collection was modified; enumeration operation may not execute." Is there another way? Thanks Updated at 03.11.2009 23:05:58I don't know TItem in my case. I just have some collection of entities. Updated at 03.11.2009 23:33:24This bug is being reproduced if I try to call ToArray() of some sub collections. For example, I have an instance of BlogPost. I execute blogPost.Comments.ToArray(), and get this exception. Updated at 03.11.2009 23:56:04Yes, there is no transaction. I don't want to use transaction, I set ReadUncommitted isolation level. And I really don't understand why should I use transactions :? Updated at 04.11.2009 0:25:54
I had been trying. SessionManager locks my DB when I just trying to make some insertions. I couldn't make it work although spent a lot of time. I almose say good-bye to hope of success with DO. All worked well with MS linq to sql, but I wanted to try your library. ...... experimenter :( Updated at 04.11.2009 1:07:32
Very simple example.
I look at the example and use SessionManager.
After this code execution I receive an Article object, and if I use ReadUncommitted isolation level, I see it in DB. But simple SELECT * FROM Article doesn't work because of lock. Of course, transaction is to be rollbacked. This is not the only example. This thread was imported from our support forum. The original discussion may contain more detailed answer. Original topic by buck. |
Likely, this happens because there is no transaction around this operation. In fact, you're:
Concerning transactions: well, most likely, you should use them. They provide isolation & atomicity at least, and normally this is what really necessary. I'll give few links on this tomorrow. If you write web application, you must just enable SessionManager module to get them provided automatically. See our ASP.NET sample (mainly, its web.config) for details. Concerning "no transactions": you'll notice DO4 anyway creates them for you, but in this case their boundaries are defined by top-level SessionBound methods you call. This ensures isolation and data consistency inside these methods - that's one of warranties DO4 provides by default. What's clear: we need to finish this part of manual ASAP... Concetning TItem & IQueryable<t> type: you can detect them ~ by the following way:
Everything else - e.g. appropriate cast & Count() call, can also be done either via reflection or inside generic method called via reflection. Tricky, but... Anyway, that's just for your info, since the best way to handle this issue it to do this inside a transaction. Trick with IQueryable is completely unnecessary. > I had been trying. Yes, I remember... > SessionManager locks my DB when I just trying to make some insertions. What does this exactly mean? Locking the whole DB seems simply impossible... What's clear is that DO4's behavior related to transactional data processing is absolutely unclear for many people. Its short explanation is very simple: DO4 always exposes exactly the same results as you'd see by running the same queries in the same conditions (transactional boundaries, etc.). Currently it does not cache any fetched data longer than your current transaction continues (although DisconnectedState & caches will violate this). This is completely different to what many other ORMs do: they cache everything until you explicitly ask them to forget this. So e.g. this code will work in DO4:
In most of ORMs last assertion would fail (let's think there are auto transactions as well, or we set the same boundaries manually there). So do I understand that sequence is the following one: 1. The transaction in CreateArticle code below is completed. 2. Query "SELECT * FROM Article" executed from e.g. SQL Server Management Studio after is waiting for release of some lock. If so, you must check which particular transaction is not completed yet - any allocated locks are released on completion of transaction they were acquired in. And about your code: 1) In web application generally you shouldn't create transactions manually. By default they're anyway provided by SessionManager (1 per each web request; transaction starts right before your first query in provided Session). 2) If there is no 1), there would be actually two transactions in your code: one is explicit, and another one is implicit one - it wraps Query<article>.Single(id). But with 1) there must be anyway just a single transaction for the whole web request (the outermost one; your inner transactions are ignored). General recommendation: turn on logging & run SQL Server profiler (turn on transaction-related events there - by default they aren't displayed) to see what happens. To turn on logging, you must add this to your Web.config:
|
Could you publish a stack trace?
Alternative way is to cast to appropriate IQueryable<titem> and get its count property. Will lead to query, but likely, it's ok as temporary workaround.