How to solve entity framework core System.ArgumentNullException - entity-framework

From the following stacktrace, I can't tell what is wrong by the error message. I ran the migration command with --verbose flag hoping it would help pinpoint the issue but zilch.
dotnet ef migrations add migwl3 --verbose
I can't find a parameter named key
System.ArgumentNullException: Value cannot be null.
Parameter name: key
at Microsoft.EntityFrameworkCore.Utilities.Check.NotNull[T](T value, String parameterName)
at Microsoft.EntityFrameworkCore.SqlServerMetadataExtensions.SqlServer(IKey key)
at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationsModelDiffer. <Add>d__41.MoveNext()
at System.Linq.Enumerable.<CastIterator>d__35`1.MoveNext()
at System.Linq.Enumerable.Single[TSource](IEnumerable`1 source)
at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationsModelDiffer. <Add>d__29.MoveNext()
at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationsModelDiffer. <DiffCollection>d__56`1.MoveNext()
at System.Linq.Enumerable.ConcatIterator`1.MoveNext()
at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationsModelDiffer.S ort(IEnumerable`1 operations, DiffContext diffContext)
at Microsoft.EntityFrameworkCore.Migrations.Design.MigrationsScaffolder.Scaf foldMigration(String migrationName, String rootNamespace, String subNamespace)
at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.AddMig ration(String name, String outputDir, String contextType)
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigrationImpl(S tring name, String outputDir, String contextType)
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.<>c__DisplayClass3_0`1.<Execute>b__0()
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Exec ute(Action action)
Value cannot be null.
Parameter name: key
Any tips on how to zero in on the issue (the project compiles fine) would be greatly appreciated

This is one of the first results from searching for Microsoft.EntityFrameworkCore.Utilities.Check.NotNull, so I'll add my stupid mistake:
I refactored a class to a different DatabaseContext, and was then calling Join between two IQueryable queries from those different contexts-- Obviously you can't do that in EntityFramework

I think Your Problem is Your Model that you not decoration [Key] attribute Or
Not use HasKey.
please share your code.

make sure that you wrote the Interface name in the constructor not the repository name.
example program
private IReviewRepository _reviewRepository;
private IPokemonRepository _pokemonRepository;
private readonly IReviewerRepository _reviewerRepository;
private IMapper _mapper;
public ReviewController(IReviewRepository reviewRepository,
IMapper mapper,
IPokemonRepository pokemonRepository,
IReviewerRepository reviewerRepository)
{
_reviewRepository = reviewRepository;
_pokemonRepository = pokemonRepository;
_reviewerRepository = reviewerRepository;
_mapper = mapper;
}
ReviewRepository instead of IReviewRepository
ReviewerRepository instead of IReviewerRepository
PokemonRepository instead of IPokemonRepository

Related

ModelBuilder HasNoKey not supported for XAF EntityFrameworkCore NonPersistent object?

I have the following class (simplified)
DomainComponent]
[VisibleInReports(true)]
public class SpTestResult
{
public string Name {get;set;}
}
And in OnModelCreating I have
modelBuilder.Entity<SpTestResult>().HasNoKey().ToTable(null); ;
The following code
public static EFCoreObjectSpaceProvider GetEfCoreObjectSpaceProvider()
{
var connectionString = GetConnectionString();
var osp = new EFCoreObjectSpaceProvider(typeof(MyDbContext),
(builder, _) => builder.UseSqlServer(connectionString));
return osp;
}
Throws an error
System.NullReferenceException
HResult=0x80004003
Message=Object reference not set to an instance of an object.
Source=DevExpress.ExpressApp.EFCore.v21.2
StackTrace:
at DevExpress.ExpressApp.EFCore.EFCoreTypeInfoSource.SetupKeyMembers(TypeInfo typeInfo)
at DevExpress.ExpressApp.EFCore.EFCoreTypeInfoSource.RegisterEntity(Type type)
at DevExpress.ExpressApp.EFCore.TypeInfoSourceHelper.InitTypeInfoSource(EFCoreObjectSpaceProvider objectSpaceProvider)
at DevExpress.ExpressApp.EFCore.EFCoreObjectSpaceProvider..ctor(Type contextType, ServiceCollection services, DbContextOptions dbContextOptions, ITypesInfo typesInfo, EFCoreTypeInfoSource typeInfoSource, String connectionString, EFCoreDatabaseProviderHandler databaseProviderHandler)
at DevExpress.ExpressApp.EFCore.EFCoreObjectSpaceProvider..ctor(Type contextType, ITypesInfo typesInfo, EFCoreTypeInfoSource typeInfoSource, String connectionString, EFCoreDatabaseProviderHandler databaseProviderHandler)
at DevExpress.ExpressApp.EFCore.EFCoreObjectSpaceProvider..ctor(Type contextType, EFCoreDatabaseProviderHandler databaseProviderHandler)
at MyApp.Module.Functions.DataHelpers.GetEfCoreObjectSpaceProvider() in
The simple work around is to include a primary key in the business object and remove the HasNoKey property in OnModelCreating.
I am wondering if it is necessary to have a primary key.
Yes, if you are going to Xaf approaches like ObjectSpace or show objects in grid etc. Xaf needs a unique Key property on all classes.

Spring JPA native query to '#IdClass' annotated table and getting "No Dialect mapping for JDBC type: 1111" [duplicate]

I'm working on a Spring JPA Application, using MySQL as database. I ensured that all spring-jpa libraries, hibernate and mysql-connector-java is loaded.
I'm running a mysql 5 instance. Here is a excerpt of my application.properties file:
spring.jpa.show-sql=false
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.database-platform=org.hibernate.dialect.MySQL5Dialect
spring.datasource.url=jdbc:mysql://localhost/mydatabase
spring.datasource.username=myuser
spring.datasource.password=SUPERSECRET
spring.datasource.driverClassName=com.mysql.jdbc.Driver
When executing an integration test, spring startsup properly but fails on creating the hibernate SessionFactory, with the exception:
org.hibernate.MappingException: No Dialect mapping for JDBC type: 1111
I think my dialects should be Mysql5Dialect, I also tried the one explicitly stating InnoDB, and the two dialect options which don't indicate the version 5. But I always end up with the same 'No Dialect mapping for JDBC type: 1111' message.
My application.properties file resides in the test/resources source folder. It is recognized by the JUnit Test runner (I previously got an exception because of an typo in it).
Are the properties I'm setting wrong? I couldn't find some official documentation on these property names but found a hint in this stackoverflow answer: https://stackoverflow.com/a/25941616/1735497
Looking forward for your answers, thanks!
BTW The application is already using spring boot.
I got the same error because my query returned a UUID column. To fix that I returned the UUID column as varchar type through the query like "cast(columnName as varchar)", then it worked.
Example:
public interface StudRepository extends JpaRepository<Mark, UUID> {
#Modifying
#Query(value = "SELECT Cast(stuid as varchar) id, SUM(marks) as marks FROM studs where group by stuid", nativeQuery = true)
List<Student> findMarkGroupByStuid();
public static interface Student(){
private String getId();
private String getMarks();
}
}
Here the answer based on the comment from SubOptimal:
The error message actually says that one column type cannot be mapped to a database type by hibernate.
In my case it was the java.util.UUID type I use as primary key in some of my entities. Just apply the annotation #Type(type="uuid-char") (for postgres #Type(type="pg-uuid"))
There is also another common use-case throwing this exception. Calling function which returns void. For more info and solution go here.
I got the same error, the problem here is UUID stored in DB is not converting to object.
I tried applying these annotations #Type(type="uuid-char") (for postgres #Type(type="pg-uuid") but it didn't work for me.
This worked for me. Suppose you want id and name from a table with a native query in JPA. Create one entity class like 'User' with fields id and name and then try converting object[] to entity we want. Here this matched data is list of array of object we are getting from query.
#Query( value = "SELECT CAST(id as varchar) id, name from users ", nativeQuery = true)
public List<Object[]> search();
public class User{
private UUID id;
private String name;
}
List<User> userList=new ArrayList<>();
for(Object[] data:matchedData){
userList.add(new User(UUID.fromString(String.valueOf(data[0])),
String.valueOf(data[1])));
}
Suppose this is the entity we have
Please Check if some Column return many have unknow Type in Query .
eg : '1' as column_name can have type unknown
and 1 as column_name is Integer is correct One .
This thing worked for me.
Finding the column that triggered the issue
First, you didn't provide the entity mapping so that we could tell what column generated this problem. For instance, it could be a UUID or a JSON column.
Now, you are using a very old Hibernate Dialect. The MySQL5Dialect is meant for MySQL 5. Most likely you are using a newer MySQL version.
So, try to use the MySQL8Dialect instead:
spring.jpa.database-platform=org.hibernate.dialect.MySQL8Dialect
Adding non-standard types
In case you got the issue because you are using a JSON column type, try to provide a custom Hibernate Dialect that supports the non-standard Type:
public class MySQL8JsonDialect
extends MySQL8Dialect{
public MySQL8JsonDialect() {
super();
this.registerHibernateType(
Types.OTHER, JsonStringType.class.getName()
);
}
}
Ans use the custom Hibernate Dialect:
<property
name="hibernate.dialect"
value="com.vladmihalcea.book.hpjp.hibernate.type.json.MySQL8JsonDialect"
/>
If you get this exception when executing SQL native queries, then you need to pass the type via addScalar:
JsonNode properties = (JsonNode) entityManager
.createNativeQuery(
"SELECT properties " +
"FROM book " +
"WHERE isbn = :isbn")
.setParameter("isbn", "978-9730228236")
.unwrap(org.hibernate.query.NativeQuery.class)
.addScalar("properties", JsonStringType.INSTANCE)
.getSingleResult();
assertEquals(
"High-Performance Java Persistence",
properties.get("title").asText()
);
Sometimes when you call sql procedure/function it might be required to return something. You can try returning void: RETURN; or string (this one worked for me): RETURN 'OK'
If you have native SQL query then fix it by adding a cast to the query.
Example:
CAST('yourString' AS varchar(50)) as anyColumnName
In my case it worked for me.
In my case, the issue was Hibernate not knowing how to deal with an UUID column. If you are using Postgres, try adding this to your resources/application.properties:
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQL9Dialect
Another simple explanation might be that you're fetching a complex Type (Entity/POJO) but do not specify the Entity to map to:
String sql = "select yourentity.* from {h-schema}Yourentity yourentity";
return entityManager.createNativeQuery(sql).getResultList();
simply add the class to map to in the createNativeQuery method:
return entityManager.createNativeQuery(sql, Yourentity.class).getResultList();
In my case the problem was that, I forgot to add resultClasses attribute when I setup my stored procedure in my User class.
#NamedStoredProcedureQuery(name = "find_email",
procedureName = "find_email", resultClasses = User.class, //<--I forgot that.
parameters = {
#StoredProcedureParameter(mode = ParameterMode.IN, name = "param_email", type = String.class)
}),
This also happens when you are using Hibernate and returning a void function. AT least w/ postgres. It doesnt know how to handle the void. I ended up having to change my void to a return int.
If you are using Postgres, check that you don't have a column of type Abstime. Abstime is an internal Postgres datatype not recognized by JPA. In this case, converting to Text using TO_CHAR could help if permitted by your business requirements.
if using Postgres
public class CustomPostgreSqlDialect extends PostgreSQL94Dialect{
#Override
public SqlTypeDescriptor remapSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescriptor)
{
switch (sqlTypeDescriptor.getSqlType())
{
case Types.CLOB:
return VarcharTypeDescriptor.INSTANCE;
case Types.BLOB:
return VarcharTypeDescriptor.INSTANCE;
case 1111://1111 should be json of pgsql
return VarcharTypeDescriptor.INSTANCE;
}
return super.remapSqlTypeDescriptor(sqlTypeDescriptor);
}
public CustomPostgreSqlDialect() {
super();
registerHibernateType(1111, "string");
}}
and use
<prop key="hibernate.dialect">com.abc.CustomPostgreSqlDialect</prop>
For anybody getting this error with an old hibernate (3.x) version:
do not write the return type in capital letters. hibernate type implementation mapping uses lowercase return types and does not convert them:
CREATE OR REPLACE FUNCTION do_something(param varchar)
RETURNS integer AS
$BODY$
...
This is for Hibernate (5.x) version
Calling database function which return JSON string/object
For this use unwrap(org.hibernate.query.NativeQuery.class).addScalar() methods for the same.
Example as below (Spring & Hibernate):
#PersistenceContext
EntityManager em;
#Override
public String getJson(String strLayerName) {
String *nativeQuery* = "select fn_layer_attributes(:layername)";
return em.createNativeQuery(*nativeQuery*).setParameter("layername", strLayerName).**unwrap(org.hibernate.query.NativeQuery.class).addScalar**("fn_layer_attributes", **new JsonNodeBinaryType()**) .getSingleResult().toString();
}
Function or procedure returning void cause some issue with JPA/Hibernate, so changing it with return integer and calling return 1 at the end of procedure may solved the problem.
SQL Type 1111 represents String.
If you are calling EntityManager.createNativeQuery(), be sure to include the resulting java class in the second parameter:
return em.createNativeQuery(sql, MyRecord.class).getResultList()
After trying many proposed solutions, including:
https://stackoverflow.com/a/59754570/349169 which is one of the solutions proposed here
https://vladmihalcea.com/hibernate-no-dialect-mapping-for-jdbc-type/
it was finally this one that fixed everything with the least amount of changes:
https://gist.github.com/agrawald/adad25d28bf6c56a7e4618fe95ee5a39
The trick is to not have #TypeDef on your class, but instead have 2 different #TypeDef in 2 different package-info.java files. One inside your production code package for your production DB, and one inside your test package for your test H2 DB.

#Query in JPA throwing null pointer exception

I am getting nullPointerException from my custom jpa method findShiftNameById() in my shift planner project(github link below). I have used #Query annotation inside ShiftDetailsRepo Interface to implement the method. Please check and let me know what could be causing this. I tried by removing nativeQuery parameter but that gives shift_details not mapped error.I tried by changing datatypes between int and long and also by changing sd.shiftName to sd.shift_name(as per the column name that is available in my actual database) but still same nullPointerException error is coming.
Github link-https://github.com/Anupam5713/shiftPlannerAPI
The method is being called in the ShiftPlanService Class inside the service package
Is there something wrong in my query?
#Query(value = "select sd.shiftName from shift_details sd where sd.shiftId=:shiftId",nativeQuery=true)
public String findShiftNameById(#Param("shiftId") int shiftId);
The following is the cause of NPE. The call to sdr is done before the dependencies are wired.
#Service
public class ShiftPlanService {
#Autowired
ShiftDetailsRepo sdr;
String S1 = sdr.findShiftNameById(1);
String S2 = sdr.findShiftNameById(2);
Move these initializations to a #PostConstruct method.
Example
#PostConstruct
public void initDetails() {
S1 = sdr.findShiftNameById(1);
S2 = sdr.findShiftNameById(2);
}

Spring Data JPA: Work with Pageable but with a specific set of fields of the entity

I am working with Spring Data 2.0.6.RELEASE.
I am working about pagination for performance and presentation purposes.
Here about performance I am talking about that if we have a lot of records is better show them through pages
I have the following and works fine:
interface PersonaDataJpaCrudRepository extends PagingAndSortingRepository<Persona, String> {
}
The #Controller works fine with:
#GetMapping(produces=MediaType.TEXT_HTML_VALUE)
public String findAll(Pageable pageable, Model model){
Through Thymeleaf I am able to apply pagination. Therefore until here the goal has been accomplished.
Note: The Persona class is annotated with JPA (#Entity, Id, etc)
Now I am concerned about the following: even when pagination works in Spring Data about the amount the records, what about of the content of each record?.
I mean: let's assume that Persona class contains 20 fields (consider any entity you want for your app), thus for a view based in html where a report only uses 4 fields (id, firstname, lastname, date), thus we have 16 unnecessary fields for each entity in memory
I have tried the following:
interface PersonaDataJpaCrudRepository extends PagingAndSortingRepository<Persona, String> {
#Query("SELECT p.id, id.nombre, id.apellido, id.fecha FROM Persona p")
#Override
Page<Persona> findAll(Pageable pageable);
}
If I do a simple print in the #Controller it fails about the following:
java.lang.ClassCastException:
[Ljava.lang.Object; cannot be cast to com.manuel.jordan.domain.Persona
If I avoid that the view fails with:
Caused by:
org.springframework.expression.spel.SpelEvaluationException:
EL1008E:
Property or field 'id' cannot be found on object of type
'java.lang.Object[]' - maybe not public or not valid?
I have read many posts in SO such as:
java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to
I understand the answer and I am agree about the Object[] return type because I am working with specific set of fields.
Is mandatory work with the complete set of fields for each entity? Should I simply accept the cost of memory about the 16 fields in this case that never are used? It for each record retrieved?
Is there a solution to work around with a specific set of fields or Object[] with the current API of Spring Data?
Have a look at Spring data Projections. For example, interface-based projections may be used to expose certain attributes through specific getter methods.
Interface:
interface PersonaSubset {
long getId();
String getNombre();
String getApellido();
String getFecha();
}
Repository method:
Page<PersonaSubset> findAll(Pageable pageable);
If you only want to read a specific set of columns you don't need to fetch the whole entity. Create a class containing requested columns - for example:
public class PersonBasicData {
private String firstName;
private String lastName;
public PersonBasicData(String firstName, String lastName) {
this.firstName = fistName;
this.lastName = lastName;
}
// getters and setters if needed
}
Then you can specify query using #Query annotation on repository method using constructor expression like this:
#Query("SELECT NEW some.package.PersonBasicData(p.firstName, p.lastName) FROM Person AS p")
You could also use Criteria API to get it done programatically:
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<PersonBasicData> query = cb.createQuery(PersonBasicData.class);
Root<Person> person = query.from(Person.class);
query.multiselect(person.get("firstName"), person.get("lastName"));
List<PersonBasicData> results = entityManager.createQuery(query).getResultList();
Be aware that instance of PersonBasicData being created just for read purposes - you won't be able to make changes to it and persist those back in your database as the class is not marked as entity and thus your JPA provider will not work with it.

PostgreSQL + Npgsql connector + MVC and SimpleMembership Not working

I've test the db connection without Websecurity and it works. I've followed the tutorial from Brice Lambson http://brice-lambson.blogspot.com.es/2012/10/entity-framework-on-postgresql.html
But when I use
WebSecurity.InitializeDatabaseConnection("myContext",
"UserProfile", "UserId", "UserName", autoCreateTables: false);
I get this exception:
System.InvalidOperationException was caught
HResult=-2146233079
Message=No user table found that has the name "UserProfile".
Source=WebMatrix.WebData
StackTrace:
in WebMatrix.WebData.SimpleMembershipProvider.ValidateUserTable()
in WebMatrix.WebData.WebSecurity.InitializeMembershipProvider(SimpleMembershipProvider simpleMembership, DatabaseConnectionInfo connect, String userTableName, String userIdColumn, String userNameColumn, Boolean createTables)
in WebMatrix.WebData.WebSecurity.InitializeProviders(DatabaseConnectionInfo connect, String userTableName, String userIdColumn, String userNameColumn, Boolean autoCreateTables)
in WebMatrix.WebData.WebSecurity.InitializeDatabaseConnection(String connectionStringName, String userTableName, String userIdColumn, String userNameColumn, Boolean autoCreateTables)
in Glink.Filters.InitializeSimpleMembershipAttribute.SimpleMembershipInitializer..ctor() en c:\Users\...\InitializeSimpleMembershipAttribute.cs:line 46
InnerException: Npgsql.NpgsqlException
HResult=-2147467259
Message=ERROR: 42601: Syntax error near «[»
Source=Npgsql
ErrorCode=-2147467259
BaseMessage=Syntax error near «[»
Code=42601
Detail=""
ErrorSql=SELECT [UserId] FROM [UserProfile] WHERE (UPPER([UserName]) = ((E'Z')))
File=src\backend\parser\scan.l
Hint=""
Line=1002
Position=8
Routine=scanner_yyerror
Severity=ERROR
Where=""
StackTrace:
in Npgsql.NpgsqlState.<ProcessBackendResponses_Ver_3>d__a.MoveNext()
in Npgsql.ForwardsOnlyDataReader.GetNextResponseObject()
in Npgsql.ForwardsOnlyDataReader.GetNextRowDescription()
in Npgsql.ForwardsOnlyDataReader.NextResult()
in Npgsql.ForwardsOnlyDataReader..ctor(IEnumerable`1 dataEnumeration, CommandBehavior behavior, NpgsqlCommand command, NotificationThreadBlock threadBlock, Boolean synchOnReadError)
in Npgsql.NpgsqlCommand.GetReader(CommandBehavior cb)
in Npgsql.NpgsqlCommand.ExecuteScalar()
in WebMatrix.Data.Database.QueryValue(String commandText, Object[] args)
in WebMatrix.WebData.DatabaseWrapper.QueryValue(String commandText, Object[] parameters)
in WebMatrix.WebData.SimpleMembershipProvider.GetUserId(IDatabase db, String userTableName, String userNameColumn, String userIdColumn, String userName)
in WebMatrix.WebData.SimpleMembershipProvider.ValidateUserTable()
InnerException:
I guess that NpgSql could not be prepared to work with SimpleMerbership, but I'd like to know if any of you had tried this.
Thank you!!
You should try Daniel Nauck's AspSQLProvider: http://dev.nauck-it.de/projects/show/aspsqlprovider
It is a PostgreSQL implementation of the ASP.NET 2.0+ Membership, Role, Profile and Session-State Store Provider.
I hope it helps.
I'd hint you to try changing "autoCreateTables: false" to "autoCreateTables: true".
Doesn't work with postgres because it injects brackets ([ ... ]) into throughout the embedded SQL:
https://github.com/aspnetwebstack/aspnetwebstack/blob/master/src/WebMatrix.WebData/SimpleMembershipProvider.cs