Entity Framework Core ExecuteSqlInterpolated gives Microsoft.Data.SqlClient.SqlException - entity-framework-core

I'm looping over a bunch of tables and have to delete records in each of them having a specific column name. I was able to get that list but the following line gives me the exception: Microsoft.Data.SqlClient.SqlException (0x80131904): Must declare the table variable "#p0".
foreach (var dsw in deleteSwModels)
{
contextCtx.Database.ExecuteSqlInterpolated($"DELETE FROM {dsw.Name} WHERE DeleteSw = 1");
}
The property Name looks like Person.Address where Person is the schema name under which the table is placed.
The version of Entity Framework Core is 3.1.8

I went digging further into the exception details and in the source code at Github ef core.
I solved the problem by making use of the following statement instead:
contextCtx.Database.ExecuteSqlRaw($"DELETE FROM {dsw.Name} WHERE DeleteSw = 1");
I hope it helps someone else in the future.

Related

Prevent EF from creating a new table during migration

I have an entity for which I don't want a table. The entity is used to generate a report and is populated using a SQL query:
public IEnumerable<Entities.MembersReportRow> Get()
{
return _context.MembersReportRows
.FromSqlRaw(#"
SELECT...")
.ToList();
}
Using modelBuilder.Ignore<MembersReportRow>(); stops the code for creating the table from being added to the migration, but then the method above stops working with error:
Cannot create a DbSet for 'MembersReportRow' because this type is not
included in the model for the context.
I've also tried:
modelBuilder.
.HasNoKey()
.ToSqlQuery(#"
SELECT...
");
...but the code to create the table still gets created in the migration, which surprises me a little as I'm specifically stating "ToSqlQuery".
Any help would be appreciated!

Delete link table entry but not referenced table entries

I am using Entity Framework database-first model. I have 2 tables that are referenced by a link table.
For example:
When I update my edmx file from my database this creates the expected model:
Now what I want to do is delete an entry from the Product_User table without deleting the referenced entry in either of the related tables (Product or User).
I've tried both of these statements (together and separately) but neither seems to have any effect:
user.Products.Clear();
foreach (var product in products)
{
product.User = null;
}
Is what I'm trying to do possible with the model the way I have it now? And if so what am I doing wrong?
I noticed I can do what I'm trying to do if I add the link table explicitly to the model but I'm trying to avoid that.
Any help would be much appreciated. Thanks.
Your seconde way to go (with a loop) seems more like the correct way.
Instead of = null try to use the .Remove() function. I guess the remove function only remove the link between the two entity, not the entities related.
See this answer : Removing many to many entity Framework

ASP.NET Identity Model First fails because of renamed AspNetUserRoles columns

Like several others I have tried to implement ASP.NET Identity Model First. Everything works fine once you have tried, errored, fumed, searched and resolved.. I thought.
See also:
ASP.NET Identity with EF Database First MVC5
http://danieleagle.com/blog/2014/05/setting-up-asp-net-identity-framework-2-0-with-database-first-vs2013-update-2-spa-template/
Course of action, summarized:
Created default project (MVC5)
Create database
Update connectionstring in the web.config
Run website, register: tables get created
Create EF Model (edmx)
Import Identity tables (everything fine up to this point)
Modified xxx.Context.tt to inherit from IdentityDbContext
Generate database script (trouble starts here)
I have solved the issues that appeared (up to the latest step). For completeness I will describe them.
Using the default Identity context
Everything works fine: tables get created, I can Register and login. This is however not the situation I want: I want to use a Model First approach.
Using the custom, model first context using the EF connectionstring
Modifying the CreatePerOwinContext so that it uses my Model First context:
public void ConfigureAuth(IAppBuilder app)
{
app.CreatePerOwinContext(CustomModelFirstDbContext.Create);
And the ApplicationUserManager so that it uses the Model First context:
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
{
var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<CustomModelFirstDbContext>()));
Results in:
Server Error in '/' Application.
The entity type ApplicationUser is not part of the model for the
current context.
Description: An unhandled exception occurred during the execution of
the current web request. Please review the stack trace for more
information about the error and where it originated in the code.
Exception Details: System.InvalidOperationException: The entity type
ApplicationUser is not part of the model for the current context.
Source Error:
An unhandled exception was generated during the execution of the
current web request. Information regarding the origin and location of
the exception can be identified using the exception stack trace below.
Stack Trace:
[InvalidOperationException: The entity type ApplicationUser is not
part of the model for the current context.]
Using the "normal" connectionstring with the custom, Model First context
An exception of type
'System.Data.Entity.Infrastructure.UnintentionalCodeFirstException'
occurred in WebApplication1.dll but was not handled in user code
Additional information: Code generated using the T4 templates for
Database First and Model First development may not work correctly if
used in Code First mode. To continue using Database First or Model
First ensure that the Entity Framework connection string is specified
in the config file of executing application. To use these classes,
that were generated from Database First or Model First, with Code
First add any additional configuration using attributes or the
DbModelBuilder API and then remove the code that throws this
exception.
So, I figured I needed the default Identity context to use Identity, and use the custom Model First context for everything else. Not the preferred solution, but acceptable.
Rolled everything back
Import Identity tables from database
(Optional) Created entities via the Model First approach
Generated database script
Both the normal project and a quick sanity check test project have the same problem with the AspNetUserRoles table. That is a junction table, and when importing it in the EF designer, everything is OK. You won't see it since it is a many to many relationship, and when inspecting the association between AspNetRole and AspNetUser it looks good.
Designer and mapping details:
However, when generating the sql script, EF modifies the keys.
Designer and mapping details:
Generated SQL script:
-- Creating table 'AspNetUserRoles'
CREATE TABLE [dbo].[AspNetUserRoles] (
[AspNetRoles_Id] nvarchar(128) NOT NULL,
[AspNetUsers_Id] nvarchar(128) NOT NULL
);
GO
In EF, you can't change the names of the mappings in the designer (thread on social.msdn.microsoft.com).
Subsequently the creation of a new user wil fail, using the originally created context because the junction table contains the wrong columns:
Server Error in '/' Application.
Invalid column name 'UserId'.
Invalid column name 'UserId'.
Invalid column name 'UserId'.
Invalid column name 'RoleId'.
Invalid column name 'UserId'.
Description: An unhandled exception occurred during the execution of
the current web request. Please review the stack trace for more
information about the error and where it originated in the code.
Exception Details: System.Data.SqlClient.SqlException: Invalid column name 'UserId'. Invalid column name 'UserId'. Invalid column name 'UserId'. Invalid column name 'RoleId'. Invalid column name 'UserId'.
Source Error:
Line 89: {
Line 90: var user = new ApplicationUser() { UserName = model.Email, Email = model.Email };
Line 91: IdentityResult result = await UserManager.CreateAsync(user, model.Password);
Line 92: if (result.Succeeded)
Line 93: {
What is the solution? Are there any alternatives than trying to change the generated script, or moving to Code First?
If you in the begginning and db is still empty than
I believe the easiest workaround is:
Create EF Model(edmx).
Right click on model "Generate Database from model".
It will create DDL file (snippet below)
Replace all wrong "AspNetUsers_Id" and "AspNetRoles_Id" for correct values.
Right click "execute".
Works for me.
-- Creating non-clustered index for FOREIGN KEY 'FK_AspNetUserRoles_AspNetUser'
CREATE INDEX [IX_FK_AspNetUserRoles_AspNetUser]
ON [dbo].[AspNetUserRoles]
([AspNetUsers_Id]); //replace for UserId
Happy coding!

Deleting all related entities in Entity Framework

I have an entity called Entry connected to multiple TimeWindows. I want to clear all time windows, then add new ones. At first I tried:
target.TimeWindows.Clear();
but this didn't really delete them, and only tried to remove the relationship, which caused an exception since there is foreign key from TimeWindows to Entry. Then I thought I should do this:
foreach (var tw in target.TimeWindows)
context.DeleteObject(tw);
but this throw an exception as well, since the collection was modified inside the foreach statement. So I thought of this:
while (target.TimeWindows.Count > 0)
context.DeleteObject(target.TimeWindows.Last());
But now I am a bit concerned about using Count property, because it might cause a SQL SELECT COUNT statement to be executed. Does it? If yes, how can I delete all time windows in Entity Framework?
Calling count on navigation property will cause select only if lazy loading is enabled and the property is not loaded yet. So the first call can cause something like:
SELECT * FROM TimeWindows WHERE TargetId = #targetId
and all count evaluations will just execute on loaded data.
You can also use this to avoid the second exception:
foreach (var tw in target.TimeWindows.ToList())
context.DeleteObject(tw);
Or you can change your database and model to support identifying relation (FK to parent will became part of TimeWindow's PK) and in such case your first code snippet will work.

EF retrieve entities from undefined table/view

Is it possible to retrieve records from a view that has not been defined in the model and to retrieve his columns value by using column name or ordinal ?
I write this code :
AppContext ctx = new AppContext("name=DbConnString");
string commandText = "SELECT V.ID, V.Code, V.Description FROM vw_UserDefinedView AS V";
ObjectQuery<DbDataRecord> query = new ObjectQuery<DbDataRecord>(commandText, ctx);
but an exception occurred when I try to execute it :
'vw_UserDefinedView' could not be resolved in the current scope or context. Make sure that all referenced variables are in scope, that required schemas are loaded, and that namespaces are referenced correctly. Near simple identifier, line 1, column 43.
Is there a way to accomplish this using Entity Framework and ObjectContext (or DbContext) ?
Best regards,
Alberto
No, this is not possible. As the message already states: "'vw_UserDefinedView' could not be resolved in the current scope or context." This view is not known to the context (.edmx). You have to realize that you are querying the Entity Model and not the Database!
If you don't want this view (for whatever reason) in your Entity Model, then simply use SqlCommand, SqlConnection and SqlDataReader to execute your statements concerning vw_UserDefinedView.
UPDATE
Maybe this link can help you further: Entity Framework : Add Properties/Entities during runtime