Developer forum

Forum » PIM » (DW 10.19.6) Dynamic SQL generation is not supported

(DW 10.19.6) Dynamic SQL generation is not supported

Gunnar Örn Baldursson
Reply

Hi, we've setup the production env for a new client this week and we're getting this exception when saving products. Any ideas what could be the cause? This is setup the same way as the test environment (same SQL Server, same .NET version) where this exception isn't happening.. EcomProductCategoryFieldValue does have a composite PK and I didn't find anything wrong with the sql login so I dunno, any help would be appreciated. DW Version is 10.19.6+a133ac78a48adf2e331a77b81a348a1f9b911f71

2025-10-03 16:09:47.8250: Management API request failed. Trace ID: 00-faec4f3afa605089d99b01cd9d3a64ab-d00bb4957cb04cd2-00. System.InvalidOperationException: Dynamic SQL generation is not supported against a SelectCommand that does not return any base table information.
   at System.Data.Common.DbCommandBuilder.BuildCache(Boolean closeConnection, Boolean useColumnsForParameterNames)
   at System.Data.Common.DbCommandBuilder.GetInsertCommand(DataRow dataRow, Boolean useColumnsForParameterNames)
   at Dynamicweb.Data.DatabaseProvider.PrepareAdapter(IDbDataAdapter adapter)
   at Dynamicweb.Data.Database.CreatePreparedAdapter(IDbCommand command, Boolean tryFillIdentity)
   at Dynamicweb.Data.Database.CreatePreparedAdapter(CommandBuilder commandBuilder, IDbConnection connection, IDbTransaction transaction, Boolean tryFillIdentity)
   at Dynamicweb.Data.Database.CreatePreparedAdapter(CommandBuilder commandBuilder, IDbConnection connection, IDbTransaction transaction)
   at Dynamicweb.Ecommerce.ProductCategoryFieldValueRepository.SaveProductValues(ProductKey productKey, Dictionary`2 productValues, Boolean deleteExistingValues)
   at Dynamicweb.Ecommerce.Products.Categories.ProductCategoryFieldValueService.SaveProductValues(ProductKey productKey, Dictionary`2 productValues, Boolean deleteExistingValues)
   at Dynamicweb.Ecommerce.Products.ProductService.SaveAndConfirmInternal(Product product, String productId, String productVariantId, String productLanguageId, Boolean skipExtendedSave, Product productPrevState)
   at Dynamicweb.Ecommerce.Products.ProductService.SaveAndConfirm(Product product, String productId, String productVariantId, String productLanguageId, Boolean skipExtendedSave)
   at Dynamicweb.Ecommerce.Products.ProductService.SaveAndConfirm(Product product, String productId, String productVariantId, String productLanguageId)
   at Dynamicweb.Products.UI.Commands.ProductSaveCommand.Handle()
   at Dynamicweb.Management.Api.Controllers.Api.DataController.GetCommandResult(Type commandType, Type queryType, String body)
   at Dynamicweb.Management.Api.Controllers.Api.DataController.Post(String command, Object body)
   at lambda_method148(Closure, Object)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.AwaitableObjectResultExecutor.Execute(ActionContext actionContext, IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|20_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddlewareImpl.g__Awaited|10_0(ExceptionHandlerMiddlewareImpl middleware, HttpContext context, Task task)
2025-10-03 16:09:47.8276: Request headers: [
  "Accept",
  "Accept-Encoding",
  "Accept-Language",
  "Authorization",
  "Connection",
  "Content-Length",
  "Content-Type",
  "Cookie",
  "Host",
  "Referer",
  "TE",
  "User-Agent",
  "origin",
  "sec-fetch-dest",
  "sec-fetch-mode",
  "sec-fetch-site",
  "priority"
]
2025-10-03 16:09:47.8278: Request item keys: [
  "DW_Current_ExecutionTable"
]
2025-10-03 16:09:47.8279: Request form: []

Replies

 
Nicolai Pedersen Dynamicweb Employee
Nicolai Pedersen
Reply

It can be missing keys or missing permissions on the db user

Can you run this on both database:

sp_help 'EcomProductCategoryFieldValue'

Ensure the SQL login has at least VIEW DEFINITION on the database

 

 
Gunnar Örn Baldursson
Reply

Hi, absolutely, here are screenshots comparing the sp_help output for each DB, they look the same to me, aside from some timestamps and index names.

Prod:

And here's from test

Test:

it looks the same to me, I tried creating a new user in prod to try and isolate the problem to the user but the issue persists for the new user. I used the following command to create the new user (the previous user was created following the steps here https://doc.dynamicweb.dev/documentation/fundamentals/setup/installation/install-db.html#set-the-sql-user-database-permissions)

CREATE USER [dw_test_user] FOR LOGIN [dw_test_user] WITH DEFAULT_SCHEMA = [dbo];
ALTER ROLE [db_datareader] ADD MEMBER [dw_test_user];
ALTER ROLE [db_datawriter] ADD MEMBER [dw_test_user];
ALTER ROLE [db_ddladmin] ADD MEMBER [dw_test_user];
GRANT VIEW DEFINITION TO [dw_test_user];

 
Nicolai Pedersen Dynamicweb Employee
Nicolai Pedersen
Reply

Well. Impossible to say...

My GPT says this....

I poked around the thread; here’s a breakdown + suggestions (and of course, caveats — I don’t have your full environment). Let’s attack this with a detective’s rigor.


What the problem is (as far as we can tell)

The original poster (Gunnar) gets this error in production when saving products:

System.InvalidOperationException: Dynamic SQL generation is not supported against a SelectCommand that does not return any base table information. (doc.dynamicweb.com)

And from the stack:

DatabaseProvider.PrepareAdapter → CreatePreparedAdapter → BuildCache → … → SaveProductValues → SaveAndConfirm → …

In short: some ADO.NET / DataAdapter internal logic is trying to auto-generate INSERT commands (or parameterized commands) based on a SelectCommand. But the SelectCommand is something that doesn’t expose “base table information” (likely missing metadata, or is a view, or is too complex), so the system says: it can’t do dynamic SQL generation here.

In other words: the data layer is trying to infer how to insert/update rows from the “shape” of the select, but it can’t because the select is not simple enough (no underlying single base table with sufficient metadata).

That’s the exception cause. The question is: why is this happening in prod but not in test, given the environments are supposed to be analogous.

The forum replies suggest (and this is a good direction) that it may be due to missing keys or missing permissions for the DB user. Nicolai suggests:

  1. Run sp_help 'EcomProductCategoryFieldValue' in both DBs to compare schema. (doc.dynamicweb.com)

  2. Ensure the SQL login has VIEW DEFINITION permission on the database. (doc.dynamicweb.com)

The OP responds: they did the sp_help and the outputs look “the same” (barring minor things). They also tried creating a fresh user in prod with the expected roles (db_datareader, db_datawriter, db_ddladmin) + VIEW DEFINITION. Yet the problem persists. (doc.dynamicweb.com)

So:

  • The schema as seen seems to match

  • The DB user permissions (on paper) seem to be correct

Therefore, the cause is more subtle. Could be:

  • A difference in SQL Server version / compatibility level

  • A misalignment in schema (something non-obvious) like missing constraints, triggers, computed columns, or metadata

  • A difference in how the queries are executed (perhaps in one environment there’s some view, or wrapper, or alias)

  • A difference in how Dynamicweb is configured (maybe in test you use a simpler adapter path, but prod uses a slightly different code path, causing SelectCommand to be non-trivial)

  • Possibly permissions not just at database level, but at schema / object / extended permission level (like on views / synonyms / metadata objects)

  • Some layer of abstraction (synonym or schema redirection) that hides base table info in prod


Steps to systematically troubleshoot (my “wizard checklist”)

Below is a plan. Work down the list; if one fails, go deeper. Take notes as you go — sometimes the smallest mismatch is the culprit.

Step What to do What to check / expected behavior What if it fails / clues to next step
1. Compare full table metadata Use INFORMATION_SCHEMA views or sys.* catalog, not just sp_help. Compare the column definitions, constraints, computed columns, defaults, identity, etc. Also check if there are triggers, or indexed views, or partitioning. They should match exactly for EcomProductCategoryFieldValue (and any dependent tables) between test & prod. If there is a difference, that’s the likely culprit — e.g. a column with no default, or missing constraint, or missing primary key.
2. Check schema ownership / synonyms / schema binding In prod, might there be a schema name mismatch or synonym? Or maybe a view rather than base table? Check if the SelectCommand is referencing something weird (view, join) that confuses the adapter. The base table must be directly referenced (or the adapter must be able to resolve metadata). If you discover that SelectCommand is hitting a view or has a join, that might break the auto-generation. In that case, you may need explicit SQL (not dynamic generation).
3. Check SQL Server compatibility / version differences Are the two environments running the same SQL Server version / compatibility mode? Differences can affect metadata visibility. They should match, or at least be similar enough not to disable metadata exposure. If there's a discrepancy, try aligning them or see which features are disallowed in prod.
4. Validate permissions in prod beyond generic ones Even though the user has VIEW DEFINITION and roles, check:    
– Does the user have metadata permissions on all schemas / tables involved?      
– Does it have access to Extended Properties / SQL Server system catalogs?      
– Are there DENY rules that override permissions?      
Try connecting with the same user and querying sys.columns, sys.objects, sys.foreign_keys, etc. The user should be able to see the metadata (column definitions, keys, constraints). If sys.columns or other catalogs return blank / limited rows, metadata access is restricted — that’s likely the block.  
5. Enable tracing / logging Turn on SQL Server Profiler / Extended Events to see what the SelectCommand is when the save is attempted. What SQL is sent? Does it contain joins, subqueries, or something that masks base table info? You want to see the raw SQL. That will give clues whether the command is “simple” or “complex.” If it’s complex, you know why metadata inference fails. That lets you either simplify the query or override the dynamic generation.
6. Try a minimal test from prod Outside of Dynamicweb, write a tiny ADO.NET snippet using the same connection (same user) to do a simple SELECT → DataAdapter → Insert on EcomProductCategoryFieldValue. Does the “dynamic SQL generation” work or break the same way? If the same error occurs, then it’s not strictly a Dynamicweb bug but a DB-level / permission / schema issue. That confirms the scope. Then you can isolate whether the query itself is the issue.
7. Consider overriding / disabling dynamic generation If dynamic generation fails, you may need to switch to explicit commands / stored procedures for that particular repository in the code. Perhaps Dynamicweb has a configuration or extension point to supply custom SQL instead. The save works once you supply explicit INSERT / UPDATE / DELETE commands instead of relying on inference. If this solves it, it’s a workaround — still better to understand why dynamic generation can’t do its job in prod.

Hypotheses (and what to test to validate them)

Here are some “theories” about what might be going on. Test these once you have visibility into metadata / SQL:

  • Hypothesis A: The table has no primary key or the PK is composite in an unexpected way
    The dynamic command builder often needs a stable primary key (or at least unique key) to map columns. If the PK is missing, or if the user cannot see it (due to permission or schema), the metadata inference fails.

  • Hypothesis B: The SELECT is too complex (in a view //from join / with computed columns) so that the underlying “base table” cannot be resolved
    In test, maybe Dynamicweb is hitting the raw table, but in prod there's a view or security wrapper. If so, the command builder says “I can’t resolve which base table(s) are involved.”

  • Hypothesis C: Permissions / metadata exposure is partially blocked
    The DB user cannot “see” certain constraints, keys, or extended properties, so the command builder can’t infer them — even if they exist. The VIEW DEFINITION may not be sufficient for some objects, or may be overridden by DENY rules.

  • Hypothesis D: Differences in database collation, compatibility level, or SQL Server version
    Maybe in prod some feature is disabled or metadata behavior changed, preventing type introspection.

  • Hypothesis E: A misconfiguration or patch difference in Dynamicweb between test and prod
    Perhaps some updated assembly or code path in prod is more strict / newer version, invoking a different DataAdapter logic.


What I’d do right away if I were debugging this hands-on

If I were in your shoes (with access to both production and test):

  1. Run full metadata dumps of EcomProductCategoryFieldValue in both environments: e.g.:

    SELECT * 
    FROM sys.columns c 
      JOIN sys.tables t ON c.object_id = t.object_id
    WHERE t.name = 'EcomProductCategoryFieldValue';
    

    Also join with sys.index_columns, sys.indexes, sys.key_constraints, etc.

  2. As the problematic DB user in prod, try:

    SELECT * FROM sys.columns WHERE object_id = OBJECT_ID('EcomProductCategoryFieldValue');
    

    If this returns no rows (or partial), that’s a red flag.

  3. Trace the SQL being executed when the save is triggered (via SQL Profiler / Extended Events). Examine the initial SELECT that is used by the adapter. See if it has weird aliases, joins, views, etc.

  4. Compare the connection string / provider configuration between test and prod. Maybe there’s a subtle difference: e.g. MultipleActiveResultSets, CommandTimeout, Enlist, or a different provider that changes how the DataAdapter is constructed.

  5. Try writing a minimal repro: use the same user credentials and from a simple console app trigger a DataAdapter on that table to see if dynamic generation works or fails.

  6. If all else fails, override the adapter behavior in your code (in Dynamicweb extension) and supply explicit SQL for inserts instead of relying on dynamic generation.

 

 
Gunnar Örn Baldursson
Reply

turned out it was a bug in the SQL Sever Version (I assume) since the issue was solved by getting the system guys to apply a newer CU

 
Nicolai Pedersen Dynamicweb Employee
Nicolai Pedersen
Reply

IT - you never know what you are gonna get :-). Good find.

Thank you for reporting back.

BR Nicolai

 

You must be logged in to post in the forum