I've implemented what i consider a fairly standard ASP Identity using Entity Framework. I've added a couple of properties to the standard AspNetUser table but I have the username column as a non nullable column.
However when the SignInManager processes the PasswordSignInAsync it generated the following sql:
SELECT TOP (1)
[Extent1].[Id] AS [Id],
[Extent1].[FullName] AS [FullName],
[Extent1].[ClientId] AS [ClientId],
[Extent1].[FirstName] AS [FirstName],
[Extent1].[LastName] AS [LastName],
[Extent1].[DateCreated] AS [DateCreated],
[Extent1].[UserOid] AS [UserOid],
[Extent1].[Email] AS [Email],
[Extent1].[EmailConfirmed] AS [EmailConfirmed],
[Extent1].[PasswordHash] AS [PasswordHash],
[Extent1].[SecurityStamp] AS [SecurityStamp],
[Extent1].[PhoneNumber] AS [PhoneNumber],
[Extent1].[PhoneNumberConfirmed] AS [PhoneNumberConfirmed],
[Extent1].[TwoFactorEnabled] AS [TwoFactorEnabled],
[Extent1].[LockoutEndDateUtc] AS [LockoutEndDateUtc],
[Extent1].[LockoutEnabled] AS [LockoutEnabled],
[Extent1].[AccessFailedCount] AS [AccessFailedCount],
[Extent1].[UserName] AS [UserName]
FROM [dbo].[AspNetUsers] AS [Extent1]
WHERE
(
UPPER([Extent1].[UserName]) = UPPER(#p__linq__0)
)
OR
(
(UPPER([Extent1].[UserName]) IS NULL)
AND (UPPER(#p__linq__0) IS NULL)
)
Can anyone tell me the following:
1. Why is EF generating the Is NULL clauses in the where clause when the username cannot be null?
2. How to stop this.
3. Is there anyway to stop the Upper statement for the Username?
1) this extra clause will be rulled out by SQL Server (presuming this is what you use) optimisation engine. But I suspect this is generated this way because your EF model does not have [Required] decorating Username property. And Username is a string and strings in .Net can be null. And when EF generates queries it does not check every column type - it looks on the the models(classes), so in EF eyes your Username column is nullable.
This is a good reason to use migrations and not modify the underlying DB by hand.
2) You see Upper because this is the way the linq query is written in the underlying storage in Identity (source, search for FindByNameAsync):
public virtual Task<TUser> FindByNameAsync(string userName)
{
ThrowIfDisposed();
return GetUserAggregateAsync(u => u.UserName.ToUpper() == userName.ToUpper());
}
.ToUppse() here is getting translated by EF into Upper in your SQL.
You can avoid this by implementing your own UserStore. But this might be too much work for what it is worth.
Related
My trivial problem is this: I need to select a single field from a table filtering by the Id field.
Something that in SQL I would simply write like this:
SELECT Field FROM {Table} WHERE Id = 1
The table name is variable.
How do I do this very trivial Query with EF Core 3.1 considering that the table name can vary?
I have already tried
context.Database.ExecuteSqlCommand($"SELECT TOP 1 Field FROM {table} WHERE Id={id}")
but I cannot read the result (it always returns -1)
I also tried this:
var test = context.Set<T>()
.FromSqlRaw($"SELECT Id FROM {table}")
.FirstOrDefault();
but give me an error because it wants all the fields in the select statement
Thanks for the support
I am using EF Core 1.1 and have a query like
var list=from l in context.Users
where l.SomeProp==someVal
select l;
I have a UDF which returns a table of Id's and I basically want to generate the following query:
select * from Users where SomeProp=#someVal and SomeId in (select id from fn_myfunc(#id))
Is this possible to do?
I think you are limited to running a raw SQL query against the database to be able to use a table valued function. For example:
var query = #"SELECT * FROM Users WHERE SomeProp = {0}
AND SomeId IN (SELECT id FROM fn_myfunc({1})";
var users = context.Users
.FromSql(query, someProp, someId)
.ToList();
There are some limitations with this method. From the docs:
SQL queries can only be used to return entity types that are part of your model. There is an enhancement on our backlog to enable returning ad-hoc types from raw SQL queries.
The SQL query must return data for all properties of the entity type.
The column names in the result set must match the column names that properties are mapped to. Note this is different from EF6.x where property/column mapping was ignored for raw SQL queries and result set column names had to match the property names.
The SQL query cannot contain related data. However, in many cases you can compose on top of the query using the Include operator to return related data.
You can return related data (i.e. Include) like this:
var users = context.Users
.FromSql(query, someProp, someId)
.Include(u => u.OtherThings)
.ToList();
If you need to do anything more complex, then you would need to either drop down to using raw data access (like ADO.Net) or another ORM. I know people who use EF Core for the bulk of the work and then occasionally drop into Dapper for performance or raw SQL that doesn't suit EF.
I am using
length(ze.string)>2 in openJpa query. but i am getting
SQLCODE=-440, SQLSTATE=42884, SQLERRMC=CHAR_LENGTH;FUNCTION, DRIVER=3.53.95 {prepstmnt 1776269692 SELECT t0.f1, t0.f2, t0.f3, t0.f4, t0.f5, t0.f6, t0.f7, t0.f8, t0.f9, t0.f10, t0.f11, t0.f12, t0.f13, t0.f14, t0.f15, t0.f16, t0.f17 FROM table t0 WHERE (t0.f1 = ? AND CHAR_LENGTH(?) > ? AND .....
In plain query when i do length operation i am getting record but using jpa its not working. I looked Here used size it doesn't work. and the field is varchar and db2. trying from past 1 hour.
DB2 requires use of the SQL function LENGTH, yet OpenJPA seems to be incorrectly converting your JPQL to use SQL function CHAR_LENGTH (hence the error message - not that DB2 gives out clear messages saying what is wrong, who knows what SQLCODE=-440 is without having to search!!).
Raise a bug on your JPA provider.
See https://www.ibm.com/support/knowledgecenter/SSEPGG_9.7.0/com.ibm.db2.luw.sql.ref.doc/doc/r0000818.html
You would need to give more details about your entity, persistence.xml, and query to get to the bottom or this. However, I do not see how OpenJPA would use CHAR_LENGTH instead of LENGTH for DB2. Let me explain. If you look at DBDictionary here:
https://svn.apache.org/viewvc/openjpa/branches/2.2.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java?view=markup
You can see it defines something called "stringLengthFunction" as follows:
public String stringLengthFunction = "CHAR_LENGTH({0})";
This is the string length function which should be used for each individual dictionary (i.e. Database config). However, for DB2, the AbstractDB2Dictionary, see here:
https://svn.apache.org/viewvc/openjpa/branches/2.2.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/AbstractDB2Dictionary.java?view=markup
overrides this as follows:
stringLengthFunction = "LENGTH({0})";
Given this, for DB2, LENGTH should be used. I took the following simple query:
"select me.id from MyEntity me where length(me.name)>2"
And executed it on OpenJPA using DB2, and I got this:
SELECT t0.ID FROM MYENTITY t0 WHERE (CAST(LENGTH(t0.ID) AS BIGINT) > CAST(? AS BIGINT)) [params=(long) 2]
Thanks,
Heath Thomann
I am using Entity Framework 5 and doing a simple query to get a few users from a table.
The SQL database is already created so I use my entities as a way to map what I have.
When I run my query I detect that other queries were executed and 2 of them with errors:
QUERY 1
ERROR: Invalid object name 'dbo.__MigrationHistory'.
SELECT
[GroupBy1].[A1] AS [C1]
FROM (
SELECT
COUNT(1) AS [A1]
FROM [dbo].[__MigrationHistory] AS [Extent1]
) AS [GroupBy1]
QUERY 2
ERROR: Invalid object name 'dbo.EdmMetadata'.
SELECT TOP (1)
[Extent1].[Id] AS [Id],
[Extent1].[ModelHash] AS [ModelHash]
FROM [dbo].[EdmMetadata] AS [Extent1]
ORDER BY [Extent1].[Id] DESC
Why is that?
I do not have dbo.EdmMetadata and dbo.__MigrationHistory tables in my database as the database already existed.
How to solve this?
Since the database is already there you will not have dbo.EdmMetadata and dbo.__MigrationHistory which codefirst is expecting. And to resolve this you can try to set the SetInitializer to null.
static NameOfYourContext()
{
Database.SetInitializer<NameOfYourContext>(null);
}
You can see this in the comments section of the this post by Scott Gu
There are 3 steps you need to follow:
1- Enable migrations in package manager if you haven't done yet:
Enable-Migrations
2- Add a migration and make sure to use the -IgnoreChanges switch as you already have an existing database:
Add-Migration InitialModel -IgnoreChanges
3- Update the database. This will automatically create __MigrationHistory table for you.
Update-Database
I disabled my exception setting. and it overlooked this exception and went on to create these tables for me automatically
For some reason I feel like I'm going about this the painful way.
I have an INSERT xml list. I'm using XML because I need to pass in more than one dynamic value. Since we're saving the event, I already have that ID. What I won't know is the Group or Room ID, so I'm using XML to essentially pass in a datatable.
Here is an example INSERT portion:
IF #eventGroupTagRoomListInsert IS NOT NULL
BEGIN
INSERT INTO EventGroupTagRoomLink(EventID, RoomID, GroupTagID, IsDeleted, LastModifiedBy, SessionID)
SELECT
#eventID AS EventID,
ParamValues.Id.query('RoomId').value('.', 'int') AS RoomID,
ParamValues.Id.query('GroupTagID').value('.', 'int') AS GroupTagID,
0 AS IsDeleted,
#lastModifiedBy AS LastModifiedBy,
#sessionId AS SessionID
FROM #eventGroupTagRoomListInsert.nodes('/Entities/entity') AS ParamValues(ID)
IF ##ERROR <> 0 GOTO ERR_HANDLER
END
Is there cleaner way to do this?
I'd say yes, is acceptable.
In theory in SQL 2008 you have Table Valued Parameters which may be simpler, as syntax at least:
INSERT INTO EventGroupTagRoomLink
(EventID, RoomID, GroupTagID, IsDeleted, LastModifiedBy, SessionID)
SELECT EventID, RoomID, GroupTagID, IsDeleted, LastModifiedBy, SessionID
FROM #eventGroupTagRoomTVP
But between backward compatibility issues (does not work on 2005) and the rather unfriendly manner to present the TVP to ADO.Net (must be a datatable or DbDataReader, will not accept for example a linq query expression) I'm not sure I'd move to TVP over XML.
No problems with this approach.
I use it in several places because it's an effective wayx (especially in SQL Server 2005+) to deal with arrays and lists
Erland and his famous "Arrays and Lists" article
If you read it and the tests too, XML is usually the fastest "standalone" (no CLR needed) method