-
Notifications
You must be signed in to change notification settings - Fork 3.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature request: use LINQ-provider from linq2db #11657
Comments
@Kirill-Maurin We are supportive of creating extensions that can be used with EF Core to enhance or replace some existing built-in part of the stack. To that end, we would be happy to work with the community on adding appropriate extension points to EF Core that can be used for such things. That being said, it would have to be a community driven effort, and the majority of the code should live externally to the EF Core repo. With regard to the list of functionality that is "missing" could you be more specific on which parts are not working for you? It seems like the first three are implemented in 2.1, and #4 requires more than just changing the LINQ provider. |
Nested queries 07:14:11.3131|[1]|Entity Framework Core 2.1.0-preview1-28290 initialized 'PostgreSqlXYZContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
07:14:11.6428|[1]|Opening connection to database 'XYZ' on server 'tcp://test:1234'.
07:14:12.1828|[12]|Opened connection to database 'XYZ' on server 'tcp://test:1234'.
07:14:12.1828|[12]|Beginning transaction with isolation level 'Snapshot'.
07:14:12.4002|[7]|Compiling query model:
'from X p in DbSet<X>
select new <>f__AnonymousType4<byte[], string, int, string>(
[p].XId,
[p].IP,
[p].Port,
(from IP2Country c in DbSet<IP2Country>
where int [c].From.CompareTo([p].IP) <= 0
order by [c].From desc
select [c])
.Take(1)
.FirstOrDefault().Country
)'
07:14:12.4803|[7]|Optimized query model:
'from X p in DbSet<X>
select new <>f__AnonymousType4<byte[], string, int, string>(
[p].XId,
[p].IP,
[p].Port,
(from IP2Country c in DbSet<IP2Country>
where int [c].From.CompareTo([p].IP) <= 0
order by [c].From desc
select [c].Country)
.Take(1)
.FirstOrDefault()
)'
07:14:12.6714|[7]|(QueryContext queryContext) => IEnumerable<<>f__AnonymousType4<byte[], string, int, string>> _InterceptExceptions(
source: IEnumerable<<>f__AnonymousType4<byte[], string, int, string>> _ShapedQuery(
queryContext: queryContext,
shaperCommandContext: SelectExpression:
SELECT "p"."XId", "p"."IP", "p"."Port", (
SELECT "t".*
FROM (
SELECT "c"."Country"
FROM "IP2Country" AS "c"
WHERE "c"."From" <= "p"."IP"
ORDER BY "c"."From" DESC
LIMIT 1
) AS "t"
ORDER BY "t"."From" DESC
LIMIT 1
) AS "Country"
FROM "Xs" AS "p",
shaper: TypedProjectionShaper<ValueBufferShaper, ValueBuffer, <>f__AnonymousType4<byte[], string, int, string>>),
contextType: XYZ.PostgreSql.PostgreSqlXYZContext,
logger: DiagnosticsLogger<Query>,
queryContext: queryContext)
07:14:12.7013|[7]|Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT "p"."XId", "p"."IP", "p"."Port", (
SELECT "t".*
FROM (
SELECT "c"."Country"
FROM "IP2Country" AS "c"
WHERE "c"."From" <= "p"."IP"
ORDER BY "c"."From" DESC
LIMIT 1
) AS "t"
ORDER BY "t"."From" DESC
LIMIT 1
) AS "Country"
FROM "Xs" AS "p"
07:14:12.7589|[7]|Failed executing DbCommand (59ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT "p"."XId", "p"."IP", "p"."Port", (
SELECT "t".*
FROM (
SELECT "c"."Country"
FROM "IP2Country" AS "c"
WHERE "c"."From" <= "p"."IP"
ORDER BY "c"."From" DESC
LIMIT 1
) AS "t"
ORDER BY "t"."From" DESC
LIMIT 1
) AS "Country"
FROM "Xs" AS "p"
07:14:12.8053|[7]|An exception occurred in the database while iterating the results of a query for context type 'XYZ.PostgreSql.PostgreSqlXYZContext'.
Npgsql.PostgresException (0x80004005): 42703: column t.From does not exist
at Npgsql.NpgsqlConnector.<DoReadMessage>d__155.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at System.Runtime.CompilerServices.ValueTaskAwaiter`1.GetResult()
at Npgsql.NpgsqlConnector.<ReadMessage>d__154.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Npgsql.NpgsqlConnector.<ReadMessage>d__154.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at System.Runtime.CompilerServices.ValueTaskAwaiter`1.GetResult()
at Npgsql.NpgsqlConnector.<ReadExpecting>d__161`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at System.Runtime.CompilerServices.ValueTaskAwaiter`1.GetResult()
at Npgsql.NpgsqlDataReader.<NextResult>d__32.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Npgsql.NpgsqlDataReader.NextResult()
at Npgsql.NpgsqlCommand.<Execute>d__71.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at System.Runtime.CompilerServices.ValueTaskAwaiter`1.GetResult()
at Npgsql.NpgsqlCommand.<ExecuteDbDataReader>d__92.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at System.Runtime.CompilerServices.ValueTaskAwaiter`1.GetResult()
at Npgsql.NpgsqlCommand.ExecuteDbDataReader(CommandBehavior behavior)
at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.Execute(IRelationalConnection connection, DbCommandMethod executeMethod, IReadOnlyDictionary`2 parameterValues)
at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.ExecuteReader(IRelationalConnection connection, IReadOnlyDictionary`2 parameterValues)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.Enumerator.BufferlessMoveNext(DbContext _, Boolean buffer)
at Microsoft.EntityFrameworkCore.Storage.Internal.NpgsqlExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.Enumerator.MoveNext()
at Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider.ExceptionInterceptor`1.EnumeratorExceptionInterceptor.MoveNext() |
"group by" 14:30:47.3502|[1]|Entity Framework Core 2.1.0-preview1-28290 initialized 'PostgreSqlP2PContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
14:30:47.6162|[1]|Opening connection to database 'P2P' on server 'tcp://test:1234'.
14:30:48.0547|[13]|Opened connection to database 'P2P' on server 'tcp://test:1234'.
14:30:48.0678|[13]|Beginning transaction with isolation level 'Snapshot'.
14:30:48.2708|[5]|Compiling query model:
'from IGrouping<<>f__AnonymousType3<string, int>, YDetails> g in
(from Z2Ks t2K in DbSet<Z2Ks>
join Z2P t2P in DbSet<Z2P>
on new <>f__AnonymousType7<DateTime, int>(
[t2K].Updated,
[t2K].ZId
) equals new <>f__AnonymousType7<DateTime, int>(
[t2P].ZUpdated,
[t2P].ZId
)
join P p in DbSet<P>
on new <>f__AnonymousType0<DateTime, string>(
[t2P].PUpdated,
[t2P].PId
) equals new <>f__AnonymousType0<DateTime, string>(
[p].Updated,
[p].Id
)
join P2X p2T in DbSet<P2X>
on new <>f__AnonymousType2<DateTime, string>(
[t2P].PUpdated,
[t2P].PId
) equals new <>f__AnonymousType2<DateTime, string>(
[p2T].PUpdated,
[p2T].PId
)
join X t in DbSet<X>
on [p2T].XId equals [t].Id
where [t2K].Outdated == __MaxValue_Date_0 && [p].Outdated == __MaxValue_Date_1 && [p2T].Outdated == __MaxValue_Date_2
join Y t2P in
(from Y <generated>_1 in DbSet<Y>
select [<generated>_1]).FromSql('select t2p.*, (select i2c."Country" from "IP2Country" i2c where i2c."From" < t2p."IP" order by i2c."From" desc limit 1) from "X2Ys" t2p')
on [t].Id equals [t2P].XId
select new YDetails{
ZId = [t2K].ZId,
XId = [t].Id,
Size = [t].Size ?? 0,
IP = [t2P].IP,
Port = [t2P].Port,
Country = [t2P].Country,
Updated = [t2P].Updated
}
).GroupBy(new <>f__AnonymousType3`2(Country = [t2P].Country, ZId = [t2K].ZId), new YDetails() {ZId = [t2K].ZId, XId = [t].Id, Size = ([t].Size ?? 0), IP = [t2P].IP, Port = [t2P].Port, Country = [t2P].Country, Updated = [t2P].Updated})
from YDetails gg in [g]
select new <>f__AnonymousType4<int, string>(
[gg].ZId,
[gg].Country
)'
14:30:48.3391|[5]|Optimized query model:
'from IGrouping<<>f__AnonymousType3<string, int>, YDetails> g in
(from Z2Ks t2K in DbSet<Z2Ks>
join Z2P t2P in DbSet<Z2P>
on new <>f__AnonymousType7<DateTime, int>(
[t2K].Updated,
[t2K].ZId
) equals new <>f__AnonymousType7<DateTime, int>(
[t2P].ZUpdated,
[t2P].ZId
)
join P p in DbSet<P>
on new <>f__AnonymousType0<DateTime, string>(
[t2P].PUpdated,
[t2P].PId
) equals new <>f__AnonymousType0<DateTime, string>(
[p].Updated,
[p].Id
)
join P2X p2T in DbSet<P2X>
on new <>f__AnonymousType2<DateTime, string>(
[t2P].PUpdated,
[t2P].PId
) equals new <>f__AnonymousType2<DateTime, string>(
[p2T].PUpdated,
[p2T].PId
)
join X t in DbSet<X>
on [p2T].XId equals [t].Id
where [t2K].Outdated == __MaxValue_Date_0 && [p].Outdated == __MaxValue_Date_1 && [p2T].Outdated == __MaxValue_Date_2
join Y t2P in DbSet<Y>
on [t].Id equals [t2P].XId
select new YDetails{
ZId = [t2K].ZId,
XId = [t].Id,
Size = [t].Size ?? 0,
IP = [t2P].IP,
Port = [t2P].Port,
Country = [t2P].Country,
Updated = [t2P].Updated
}
).GroupBy(new <>f__AnonymousType3`2(Country = [t2P].Country, ZId = [t2K].ZId), new YDetails() {ZId = [t2K].ZId, XId = [t].Id, Size = ([t].Size ?? 0), IP = [t2P].IP, Port = [t2P].Port, Country = [t2P].Country, Updated = [t2P].Updated})
from YDetails gg in [g]
select new <>f__AnonymousType4<int, string>(
[gg].ZId,
[gg].Country
)'
14:30:48.5713|[4]|Disposing transaction.
14:30:48.5713|[4]|Closing connection to database 'P2P' on server 'tcp://test:1234'.
14:30:48.5812|[4]|Closed connection to database 'P2P' on server 'tcp://test:1234'. |
Extension for missed "out-the-box" features select i2c."Country" from "IP2Country" i2c where i2c."From" < t2p."IP" order by i2c."From" desc limit 1 A solution with linq2Db [Sql.Expression( "{0} <= {1}", PreferServerSide = true, IsPredicate = true )]
public static bool LessOrEqual( IPAddress left, IPAddress right ) => left.CompareTo( right ) <= 0; |
|
@Kirill-Maurin have you tried preview-2 ? |
@Kirill-Maurin i can't answer for the rest, but special PostgreSQL types (e.g. inet) are already fully supported by the Npgsql provider, and AFAIK operators on them should be translated to SQL as well. If you're seeing a problem please open an issue on Npgsql.EntityFrameworkCore.PostgreSQL with the C# code you're trying out (that's missing above) |
@roji @ErikEJ 10:52:10.4781|[1]|Entity Framework Core 2.1.0-preview2-30571 initialized 'PostgreSqlXYZContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
10:52:10.5978|[1]|Opening connection to database 'XYZ' on server 'tcp://test:1234'.
10:52:11.5554|[12]|Opened connection to database 'XYZ' on server 'tcp://test:1234'.
10:52:11.5554|[12]|Beginning transaction with isolation level 'ReadCommitted'.
10:52:11.7766|[9]|Compiling query model:
'from X2Y p in DbSet<X2Y>
select new <>f__AnonymousType3<BigInteger, string>(
[p].IP,
(from IP2Country c in DbSet<IP2Country>
where [c].From <= [p].IP
order by [c].From asc
select [c]).FirstOrDefault().Country
)'
10:52:11.8408|[9]|Optimized query model:
'from X2Y p in DbSet<X2Y>
select new <>f__AnonymousType3<BigInteger, string>(
[p].IP,
(from IP2Country c in DbSet<IP2Country>
where [c].From <= [p].IP
order by [c].From asc
select [c].Country).FirstOrDefault()
)'
10:52:12.0420|[9]|(QueryContext queryContext) => IEnumerable<<>f__AnonymousType3<BigInteger, string>> _InterceptExceptions(
source: IEnumerable<<>f__AnonymousType3<BigInteger, string>> _ShapedQuery(
queryContext: queryContext,
shaperCommandContext: SelectExpression:
SELECT p."IP", (
SELECT c."Country"
FROM "IP2Country" AS c
WHERE c."From" <= p."IP"
ORDER BY c."From"
LIMIT 1
) AS "Country"
FROM "X2Ys" AS p,
shaper: TypedProjectionShaper<ValueBufferShaper, ValueBuffer, <>f__AnonymousType3<BigInteger, string>>),
contextType: XYZ.PostgreSql.PostgreSqlXYZContext,
logger: DiagnosticsLogger<Query>,
queryContext: queryContext)
10:52:12.0750|[9]|Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT p."IP", (
SELECT c."Country"
FROM "IP2Country" AS c
WHERE c."From" <= p."IP"
ORDER BY c."From"
LIMIT 1
) AS "Country"
FROM "X2Ys" AS p
10:52:12.1803|[9]|Executed DbCommand (106ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT p."IP", (
SELECT c."Country"
FROM "IP2Country" AS c
WHERE c."From" <= p."IP"
ORDER BY c."From"
LIMIT 1
) AS "Country"
FROM "X2Ys" AS p |
Unfortunately, for my case of "group by" review-2 works no better than review-1 |
EF Core 2.1 preview2 cannot create migration
|
Nested query bug posted above. Duplicate of #11326 Fixed in 2.1.0-preview2 |
GroupBy issue seems like you are generating query and enumerator but you are not iterating it. If you are not consuming group, we don't do the work to retrieve data. Given that there are customers out there using GroupBy successfully, it seems like something is amiss in user code which is causing no sql to be seen in the logs. |
Thanks
I use the same code to reproduce. I change only query and/or LINQ-provider. 12:26:09.5150|[1]|Entity Framework Core 2.1.0-preview2-30571 initialized 'PostgreSqlXYZContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
12:26:09.6222|[1]|Opening connection to database 'XYZ' on server 'tcp://test:1234'.
12:26:10.4541|[12]|Opened connection to database 'XYZ' on server 'tcp://test:1234'.
12:26:10.4541|[12]|Beginning transaction with isolation level 'Snapshot'.
12:26:10.6298|[6]|Expression test code generated: 'E:\Temp\linq2db\ExpressionTest.0.cs'. DataConnection
12:26:11.6415|[6]|-- PostgreSQL.9.2 PostgreSQL
DECLARE @p1 Timestamp -- DateTime
SET @p1 = '2018-04-16'
DECLARE @p2 Timestamp -- DateTime
SET @p2 = '9999-12-31'
DECLARE @p3 Timestamp -- DateTime
SET @p3 = '9999-12-31'
DECLARE @p4 Timestamp -- DateTime
SET @p4 = '9999-12-31'
SELECT
t3."Code",
t3."Name",
g1.c11 as c111,
g1.c2 as c21,
g1.c3 as c31,
g1.c4 as c41
FROM
(
SELECT
"t2K"."ZId",
"t2P1".c1 as c11,
Sum(Coalesce(t."Size", 0)) as c2,
COUNT(DISTINCT t."Id") as c3,
COUNT(DISTINCT (Cast("t2P1"."IP" as VarChar(100)) || ':' || Cast("t2P1"."Port" as VarChar(11)))) as c4
FROM
"Z2Keywords" "t2K"
INNER JOIN "Z2P" "t2P" ON "t2K"."Updated" = "t2P"."ZUpdated" AND "t2K"."ZId" = "t2P"."ZId"
INNER JOIN "P" p ON "t2P"."PUpdated" = p."Updated" AND ("t2P"."PId" IS NULL AND p."Id" IS NULL OR "t2P"."PId" = p."Id")
INNER JOIN "P2Xs" "p2T" ON "t2P"."PUpdated" = "p2T"."PUpdated" AND ("t2P"."PId" IS NULL AND "p2T"."PId" IS NULL OR "t2P"."PId" = "p2T"."PId")
INNER JOIN "Xs" t ON "p2T"."XId" IS NULL AND t."Id" IS NULL OR "p2T"."XId" = t."Id"
INNER JOIN (
SELECT
t2."XId",
t2."Updated",
(
SELECT
t1."Country"
FROM
"IP2Country" t1
WHERE
t1."From" <= t2."IP"
ORDER BY
t1."From" DESC
LIMIT 1
) as c1,
t2."IP",
t2."Port"
FROM
"X2Ys" t2
) "t2P1" ON t."Id" IS NULL AND "t2P1"."XId" IS NULL OR t."Id" = "t2P1"."XId"
WHERE
"t2P1"."Updated" = :p1 AND
"p2T"."Outdated" = :p2 AND
p."Outdated" = :p3 AND
"t2K"."Outdated" = :p4
GROUP BY
"t2K"."ZId",
"t2P1".c1
) g1
INNER JOIN "Zs" t3 ON g1."ZId" = t3."Id"
DataConnection
12:26:11.9834|[6]|Query Execution Time: 00:00:00.3384215
DataConnection
12:26:12.0770|[11]|Total Execution Time: 00:00:00.6172998. Rows Count: 545.
DataConnection |
Does EF Core gives you incorrect results? Or shows you empty results when there are results? Did you verify results by EF Core? If you see that there are no results generated when you verify them, please file a new issue with detailed repro steps. (ideally a repro solution) EF Core using streaming for results. It will create the query and do all groundwork but reading actual data for server or running SQL queries (especially in the case where there are more than 1 SQL to be run), will depend on consumption of results from client code. If you are not consuming the results of the query, EF Core will not generate client objects for result. This is pattern allows you to iterate over a large result set without running out of memory because you can keep only data in memory which is needed for current iteration. Not all ORM or linq to sql translator work this way and they may be computing results even without getting enumerated. Difference in such behaviour is not indication that EF core is not working. |
Verified that if you call |
You asked for it... |
@MaceWindu |
@ajcvickers
|
@MaceWindu This is awesome. Please please continue to develop and maintain this project. With entityframework core and linq2db effectively combined there is a full feature set. This would be a very powerful ORM setup. Is there a roadmap for this project? |
@nathan-parkinson not sure what we can include into roadmap. It is pretty much feature-complete project. I think next week we can release it on nuget taking into account EF.Core 2.1 release. |
@MaceWindu Sorry, I think I'm asking the wrong question. I suppose what i'm trying to ask is whether it is a safe option to add this into my projects. Will this be maintained and released - currently the readme states it is in early preview - or is this an experimental repo that could be discontinued at any time. |
@nathan-parkinson it is in preview, because we didn't get any feedback yet from real users. We don't plan to drop this project and if it will get enought attention from users, we will consider to include it into linq2db directly later. |
@MaceWindu Thanks for the information. If I have any useful feedback I will let you know |
@MaceWindu thanks for the information on the missing extension points. Could you please create one or two new issues for these so that we can discuss them in triage? |
We periodically close 'discussion' issues that have not been updated in a long period of time. We apologize if this causes any inconvenience. We ask that if you are still encountering an issue, please log a new issue with updated information and we will investigate. |
Сurrently LINQ-provider in EF Core is far from perfect.
But there is a production-ready alternative: linq2db
EF Core model can be tranlated to linq2db mapping scheme.
This will allow very cheap access to the following functionality:
Also, EF Core team will be able to allocate more resources for the improvement of migrations, change tracker and other unique EF Core features
Now I use my own wrapper to transparently combine two ORM sharing one model
The text was updated successfully, but these errors were encountered: