I use this formula in NHibernate 3.1 :
.Formula("(SELECT b.Name FROM AdaptiveObjectModel.EntityType AS b WHERE (Structure = b.EntityTypeId))")
but after switching to NHibernate 3.2 receive this problem:
ambiguous column name Structure
The error comes from SQLserver, there are at least 2 tables with the column Structure. SQLserver does not know which one to chose. I guess that something changed in the way NHibernate interprets your query, and now sends all sql at once. Have a look in the logging or your profiler to see what the sql is your are sending to SQLserver. Then you can add the right alias before Structure.
Related
I'm using DBeaver to write script for my PostgreSQL database.
I have a PostgreSQL DB with Tables autogenerated by C#/EFCore (Microsoft ORM) - I receive SQL Error [42P01] if I don't add double quotes around table names when I cut and paste my ORM queries to DBeaver. I got [42703] for fields without double quotes. I do not have to add double quotes in C# code but it appears to be required in DBeaver?
example:
select * from Dnp3PropertyBase => SQL Error [42P01]
select * from "Dnp3PropertyBase" => OK, all results shown...
Does anybody know if I can change a parameter in DBeaver somewhere in order to enter table names and fields without double quotes?
Note: Using DBeaver 22.3.2 (latest on 2023-01-11)
Update After reading: Postgresql tables exists, but getting "relation does not exist" when querying
show search_path => public, public, "$user"
SELECT * FROM information_schema.tables => All tables are in public schema
SELECT * FROM information_schema.columns => All columns are in public schema
Question: How to be able to cut and paste my EFCore generated queries from Visual Studio output window to DBeaver query without having any errors regarding table names and field names?
First let me copy #a_horse_with_no_name comment:
Unquoted names are folded to lower case in Postgres (and to uppercase
in Oracle, DB2, Firebird, and many others). So SomeTable is in fact
stored as sometable (or SOMETABLE). However quoted identifiers have to
preserve the case and are case sensitive then. So "SomeTable" is
stored as SomeTable
Many peoples recommended me to go with snake case which I didn't want to go with initialy because all tables were auto generated by EF Core (Microsoft C# ORM). I told myself that Microsoft would do standard things. Microsoft use the exact "class" name in code as the table name , by default. That appears to me very logical in order to stay coherent and apply the same rules everywhere. C# recommended to use Camel case for classes so each table names end by default in Camel case instead of snake case.
PostgreSQL seems to promote users to use snake casing because they lower case every non double quoted names. According to a_horse_with_no_name, and I think the same, only PostgreSQL has the behavior of lower casing down every table names and field names which are not double quoted in SQL script. That behavior (changing casing for non double quoted names) appears to me as being very limitative. It also has hidden effect that could be hard to find for non initiated peoples coming from other DB world.
According to PostgreSQL doc, they recommend to use nuget package (.UseSnakeCaseNamingConvention()). It probably works fine for TPH (table per hierarchy) which is recommended by Microsoft for performance. But it does not works for table name for TPC (table per class) because of actual bugs in EFCore 7 (see Github project).
I received that message at the end of "update-database":
Both 'WindTurbine' and 'ResourceGenerator' are mapped to the table
'resource_generator'. All the entity types in a non-TPH hierarchy (one
that doesn't have a discriminator) must be mapped to different tables.
See https://go.microsoft.com/fwlink/?linkid=2130430 for more
information.
PostgreSQL doc : TPH supported OK but not for table in TPC (2023-01-12). I use TPC then I had to force each table name directly through TableAttribute.
My solution For table name, I use snake casing by manually add a "Table" attribute to each of my classes with the proper name like this sample:
[Table("water_turbine")]
public class WaterTurbine : ResourceGenerator
For fields, I use the EFCore.NamingConventions NugetPackage which works fine for fields names. Don't forget that if you have 2 classes mapped to the same object, it is because you are using TPC and did not force table name through TableAttribute.
This way all my table and fields names are snake casing and I can cut and paste any query dumped in my debugger directly in any SQL script window of DBeaver (or any SQL tool).
tl;dr: Hibernate automatically generates SQL table aliases in its queries like jurisdicti4_ or this_. Here's an example query:
SELECT
this_.id AS id2_6_3_,
this_.a_table_column AS a_table_column3_6_3_,
jurisdicti4_.b_table_column AS b_table_column4_6_3_,
FROM
app_table_a this_
LEFT OUTER JOIN jurisdiction jurisdicti4_ ON this_.jurisdiction = jurisdicti4_.name
WHERE
this_.a_table_column = ?
I'm using the Hibernate Criteria API to add some hints that need reference the SQL aliases in the query, so I need to know how to either:
specify the SQL table aliases Hibernate will use in its queries (e.g. tell it to use juris instead of jurisdicti4_ for jurisdiction, or
get hibernate to tell me the exact SQL table alias it will use for a particular table or entity (e.g. be told the alias in the query for jurisdiction will be jurisdicti4_.
Full story:
I've inherited a Java app with an Oracle DB that uses Hibernate 4.3.8 and the Hibernate Criteria API to generate some complicated search queries. It recently ran into a severe SQL performance problem that will require us to start to include hints these queries. However, we use Oracle, and its index hints are in the form of:
/*+ index (TABLE_ALIAS INDEX_NAME) */
I've successfully added the needed hints using Criteria.addHint(...), however I've had to hardcode the Hibernate-generated TABLE_ALIAS in the hint string. I'm concerned that over time, the aliases may change, so I want to either control how they're generated or be able to retrieve their values to use when adding the SQL hint.
Edit: This website describes the Hibernate SQL alias generation process: https://prismoskills.appspot.com/lessons/Hibernate/Chapter_23_-_Hibernate_alias_names.jsp
I've found that I have partial control of the SQL aliases when I programmatically set up the join like this: criteria.createAlias(associationPath, alias). The alias value I pass seems to be used as the first part of the SQL alias for the table. However, Hibernate appends some kind of generated table ID integer to that, so I'd get something like myalias4_ in the generated SQL. Also, this only seems to work in joins I setup myself in the criteria. Hibernate will often add its own based on the mappings, and I'm not sure how get this same level of partial control over those.
The following query was working fine with EF core 2 but EF core 3 would throw error!
I even could add some include after this query in EF core 2 which I let go now.
query:
// just to have an Id
var id = Guid.NewGuid();
var resutl = Context.Parties.FromSqlInterpolated($#"WITH mainOffice AS
(SELECT * FROM Parties as o1 WHERE (Discriminator = N'Office')
AND (Id = '{id}')
UNION ALL SELECT o.* FROM Parties AS o INNER JOIN mainOffice AS m
ON m.Id = o.ParentOfficeId)
SELECT * FROM mainOffice as f").ToList();
The error it produces is as follows:
FromSqlRaw or FromSqlInterpolated was called with non-composable SQL
and with a query composing over it. Consider calling AsEnumerable
after the FromSqlRaw or FromSqlInterpolated method to perform the
composition on the client side.
Knowing the following information might help:
Table "Parties" is a table per hierarchy
I tried to run the query both from the root type DbSet and the type I am interested for
No success with nether FromSqlRaw nor FromSqlInterpolated
Adding 'AsEnumerable' did not help too
Did I forget any thing? What am I doing wrong?
What does 'non-composable SQL' mean? Does it mean EF core is trying to interpret query?
I don't have the answer, but I know the reason now.
The reason this error is being generated is similar to this issue:
FromSql method when used with stored procedure cannot be composed
In my case weather or not I use any method, because the table I am trying to query is containing some different type (Table per hierarchy), my query will always be warped inside a select query to limit discriminators. Even though I write the query from the root, the wrapper select query is generated with all possible discriminators.
So it means I can only run queries that can be placed as sub query. My query can not, store procedures can not ...
I found a workaround for this issue,
You can create a view in database and a query type in your model and then run your query against this view (note that the way you do that has been changed from ef 2 to 3 as it is explained here)
So in this way inheritance and discriminators are not problems any more and query can be run.
Maybe related?
https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-3.0/breaking-changes#linq-queries-are-no-longer-evaluated-on-the-client
Efcore 2 implicity performed linq to objects on parts of a query that it could not transform to sql. This functionality was removed in efcore 3.
I'm using entity framework that needs to be run against slightly different schemas of a database.
In one database a column does not exist,but in another it is a required (not null) field.
If I was writing SQL, I could query sys.columns to see if the columns exist and adjust my sql accordingly.
How would I do the same with Entity Framework?
You can check if the column exists then, if does not exists mark it as ignored via fluent API mapping
modelBuilder.Entity<MyEntity>()
.Ignore(_ => _.MyOptProperty);
We're saving an object to NHibernate where the Id is typed Guid. Based on other things we've found we have this as a type char(36).
We create an object and save it via NHibernate. This works fine and we see 64599239BB0C1C48B44C36D9F9267830 in the column.
When we then try to load using a guid we don't get any results and NHibernate Profiler shows that the WHERE clause is looking for 0x64599239BB0C1C48B44C36D9F9267830 which isn't matching.
Obviously we're doing something wrong.. so any ideas what?
The data type on the database should be RAW, and of 16 length. This is what trying to recreate the database using NHibernate produces.