Design Meeting Notes - April 4, 2013
Revisit: Using ExecuteSqlCommand without a transaction
Last week we discussed the API for using ExecuteSqlCommand when the command cannot be executed inside a transaction. The conclusion was to provide an enum value as a parameter that would allow executing the command outside of a transaction. There were a
few new ideas, so we revisited the issue.
Idea: Provide a global flag in context.Configuration that would control this behavior for all relevant APIs, together with a general purpose mechanism for scoping flag changes with using. The problem with this is that it would be too easy to switch it on
globally and leave it on without realizing the consequences this would have. For example, it would be easy to make SaveChanges start executing without any transaction, either because the developer didn’t know that the flag caused this or because the developer
wasn’t aware of the potentially bad consequences of doing this. Therefore, while the scoping pattern is interesting in itself, we chose not to have a global flag.
There were also new ideas around the enum and its naming. Specifically:
- Should the enum name be more specifically tied to the ExecuteSqlCommand method? We decided against this because the general feeling is that it wouldn’t provide significant extra value and might prevent using the enum with other APIs in the future. Also,
in general, enums seems to be named for themselves rather than for the method(s) they are used with.
- Given the way the API is shaping up does Default add any value? Decision: no; remove it.
- Given that the enum isn’t really about the transaction’s behavior, but rather the behavior around creating/enlisting in a transaction, should the name change? Decision: probably okay as is, but slight preference for TransactionalBehavior. We also considered
Revisit: Extension method class naming
Last week we decided to keep the class name IQueryableExtensions for EF extension methods that target IQueryable. However, starting a class with an “I” prefix have been determined to break the .NET design guidelines. Therefore, we need to do something different.
Options considered were:
- Revert to DbExtensions—avoids the minor breaking change that was already inadvertently introduced with EF6. (Note that EF6 is already binary incompatible with EF5.) The downside here is that we wouldn’t choose this name if making the choice now.
- Stick to the pattern of <TypeName>Extensions, but drop the I prefix when the target type is an interface. This is as close as we can get to a consistent pattern, and seems to be common practice in the community. The downside here is that these methods
don’t work out-of-the-box with most IQueryable implementations—only with EF implementations or where another implementation has followed a specific pattern to enable support.
- Name based on “main class” that these extension methods are used with. In this case the name would be DbQueryExtensions because DbQuery is the main type of IQueryable that these extension methods are intended to work with. This would potentially provide
more useful information to people looking at the class name. There are three perceived downsides here. First, these extension methods also have first-class support for ObjectQuery, although we do our best to encourage all new code to use DbQuery. Second, DbQuery
is quite hidden in normal usage—most people never see it directly. Third, it means that we don’t have a consistent pattern for naming extension method classes.
Decision: The EF team was unable to come to consensus. The Dev Manager was designated as the person to make a choice. Decision is QueryableExtensions.
Another related issue is that IDbSetExtensions is actually duplicated in two namespaces: one is very specific to Migrations and we don’t want folks using it outside of that context. We also need to decide what to call this class, with one suggestion being
to use DbSetMigrationsExtensions. Another suggestion is to just keep the names the same since, at least when the methods are used as extension methods, the compiler has no problem with it.
Decision: Again the Dev Manager will decide. Decision is DbSetExtensions and DbSetMigrationsExtensions.
New transient error codes
The SQL Azure execution strategy was updated with a new set of transient error codes. However, many of these codes suggest that a developer make a code change to avoid the failure. For example, “The session has been terminated because of excessive memory
usage. Try modifying your query to process fewer rows.” It seems counter-productive to retry the same operation in such cases and therefore we will not include these as errors that will be automatically retried.