Giter Site home page Giter Site logo

linq2db / linq2db.entityframeworkcore Goto Github PK

View Code? Open in Web Editor NEW
437.0 24.0 39.0 2.74 MB

Bring power of Linq To DB to Entity Framework Core projects

License: MIT License

C# 99.75% PowerShell 0.12% F# 0.13%
entityframeworkcore linq2db sql linq entity-framework entity-framework-core orm dotnet-core

linq2db.entityframeworkcore's Introduction

linq2db.EntityFrameworkCore

linq2db.EntityFrameworkCore is an integration of LINQ To DB with existing EntityFrameworkCore projects. It was inspired by this issue in EF.Core repository.

Build status

Azure DevOps builds Azure DevOps builds Azure DevOps builds

Feeds

  • NuGet NuGet
  • Azure Artifacts MyGet (feed)

Unique features

  • Fast Eager Loading (incomparable faster on massive Include query)
  • Global Query Filters optimization
  • Better SQL optimization
  • Use CTE in LINQ queries
  • MERGE statement support
  • Table hints
  • Full Window functions support
  • Fast BulkCopy of millions records
  • Native SQL operations for updating, deleting, inserting records via LINQ query
  • Temporary Tables support
  • Cross Database/Linked Server queries.
  • Full Text Search extensions
  • A lot of extensions to cover ANSI SQL

How to use

In your code you need to initialize integration using following call:

LinqToDBForEFTools.Initialize();

After that you can just call DbContext and IQueryable extension methods, provided by LINQ To DB.

You can also register additional options (like interceptors) for LinqToDB during EF context registration, here is an example:

var optionsBuilder = new DbContextOptionsBuilder<MyDbContext>();
optionsBuilder.UseSqlite();
optionsBuilder.UseLinqToDB(builder =>
{
    // add custom command interceptor
    builder.AddInterceptor(new MyCommandInterceptor());
    // add additional mappings
    builder.AddMappingSchema(myCustomMappings);
    // configure SQL Server dialect explicitly
    builder.AddCustomOptions(o => o.UseSqlServer(SqlServerVersion.v2022));
});

There are many extensions for CRUD Operations missing in vanilla EF (watch our video):

// fast insert big recordsets
ctx.BulkCopy(new BulkCopyOptions {...}, items);

// query for retrieving products that do not have duplicates by Name
var query =
    from p in ctx.Products
    from op in ctx.Products.LeftJoin(op => op.ProductID != p.ProductID && op.Name == p.Name)
    where Sql.ToNullable(op.ProductID) == null
    select p;

// insert these records into the same or another table
query.Insert(ctx.Products.ToLinqToDBTable(), s => new Product { Name = s.Name ... });

// update these records by changing name based on previous value
query.Update(prev => new Product { Name = "U_" + prev.Name ... });

// delete records that matched by query
query.Delete();

Some extensions require LINQ To DB ITable<T> interface, which could be acquired from DbSet<T> using ToLinqToDBTable() extension method.

For ITable<T> interface LINQ To DB provides several extensions that may be useful for complex databases and custom queries:

table = table.TableName("NewTableName");     // change table name in query
table = table.DatabaseName("OtherDatabase"); // change database name, useful for cross database queries.
table = table.OwnerName("OtherOwner");       // change owner.

// inserting into other existing table Products2
query.Insert(ctx.Products.ToLinqToDBTable().TableName("Products2"), s => new Product { Name = s.Name ... });

It is not required to work directly with LINQ To DB DataConnection class but there are several ways to do that. LINQ To DB will try to reuse your configuration and select appropriate data provider:

// uing DbContext
using (var dc = ctx.CreateLinqToDBConnection())
{
   // linq queries using linq2db extensions
}

// using DbContextOptions
using (var dc = options.CreateLinqToDBConnection())
{
   // linq queries using linq2db extensions
}

You can use all LINQ To DB extension functions in your EF linq queries. Just ensure you have called ToLinqToDB() function before materializing objects for synchronous methods.

Since EF Core have defined it's own asynchronous methods, we have to duplicate them to resolve naming collisions. Async methods have the same name but with LinqToDB suffix. E.g. ToListAsyncLinqToDB(), SumAsyncLinqToDB(), ect. The same methods are added whe you need EF Core query processing but there is collision with LINQ To DB and they have extensions with EF suffix - ToListAsyncEF(), SumAsyncEF(), ect.

using (var ctx = CreateAdventureWorksContext())
{
    var productsWithModelCount =
        from p in ctx.Products
        select new
        {
            // Window Function
            Count = Sql.Ext.Count().Over().PartitionBy(p.ProductModelID).ToValue(),
            Product = p
        };

    var neededRecords =
        from p in productsWithModelCount
        where p.Count.Between(2, 4) // LINQ To DB extension
        select new
        {
            p.Product.Name,
            p.Product.Color,
            p.Product.Size,
            // retrieving value from column dynamically
            PhotoFileName = Sql.Property<string>(p.Product, "ThumbnailPhotoFileName")
        };

    // ensure we have replaced EF context
    var items1 = neededRecords.ToLinqToDB().ToArray();       
    
    // async version
    var items2 = await neededRecords.ToLinqToDB().ToArrayAsync(); 
    
    // and simple bonus - how to generate SQL
    var sql = neededRecords.ToLinqToDB().ToString();
}

Also check existing tests in test project for some examples.

Why should I want to use it?

There are many reasons. Some of them:

  • you want to use advanced SQL functionality, not supported or poorly supported by EntityFrameworkCore like BulkCopy support, SQL MERGE operations, convinient DML (Insert/Delete/Update) operations and many-many-many other features LINQ To DB provides, but you need change tracking functionality that EntityFramework provides.
  • you want to migrate to LINQ To DB, but need to do it step-by-step.
  • just because LINQ To DB is cool.

Current status

Below is a list of providers, that should work right now:

  • SQL Server
  • MySQL (including Devart and Pomelo providers)
  • PostgreSQL (Both npgsql and Devart providers)
  • SQLite (including Devart provider)
  • Firebird
  • DB2 LUW
  • Oracle
  • SQL Server CE

Known limitations

  • No Lazy loading
  • No way to work with in-memory database
  • No TPT (table per type) support
  • No many-to-many support

Help! It doesn't work!

If you encounter any issue with this library, first check issues to see if it was already reported and if not, feel free to report new issue.

linq2db.entityframeworkcore's People

Contributors

ili avatar jlukawska avatar kirill-maurin avatar macewindu avatar plukawski avatar sdanyliv avatar shane32 avatar tarasverq avatar theconstructor avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

linq2db.entityframeworkcore's Issues

`ToListAsync` overlaps with EF's extensions

When using Microsoft.EntityFrameworkCore and LinqToDB on the same file, and attempt to invoke ToListAsync, you get an error:

The call is ambiguous between the following methods or properties: 'Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync(System.Linq.IQueryable, System.Threading.CancellationToken)' and 'LinqToDB.AsyncExtensions.ToListAsync(System.Linq.IQueryable, System.Threading.CancellationToken)'

I am not sure what the best of solving this, but as a temporary work around, I am creating my own static class, on my own namespace, that only exports the necessary non-conflicting extensions that I need. Such that when using Microsoft.EntityFrameworkCore and MyNamespace, I can still use LinqToDB and EF on the same file.

Any other ideas on how to fix this? Or how are other people dealing with the conflicting extension methods?

Support In-Memory Database

Throw exception, if use UseInMemoryDatabase in Microsoft.EntityFrameworkCore.InMemory.

System.InvalidCastException: 
'Microsoft.EntityFrameworkCore.InMemory.Query.Internal.InMemoryQueryContextFactory' 
'Microsoft.EntityFrameworkCore.Query.RelationalQueryContextFactory'

Different results (and SQL queries) by SingleAsyncEF and SingleAsyncLinqToDB with self-referenced entity

A very simple query with an entity referencing itself gives an incorrect result (the relation unfolds in the opposite direction).

My database: PostgreSQL

Software versions

    <TargetFramework>netcoreapp3.1</TargetFramework>
    <PackageReference Include="linq2db.EntityFrameworkCore" Version="3.7.0" />
    <PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.9" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.9"/>
    <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="3.1.4" />

My entity:

        public sealed class TestEntity
        {
            public int Id { get; set; }

            public int? ParentId { get; set; }

            public TestEntity Parent { get; set; }
            public List<TestEntity> Childs { get; set; }

            public string Name { get; set; }
        }

Configuration

modelBuilder.Entity<TestEntity>(b =>
{
	b.HasKey(x => new { x.Id });

	b.HasOne(x => x.Parent)
		.WithMany(x => x.Childs)
		.HasForeignKey(x => new { x.ParentId })
		.HasPrincipalKey(x => new { x.Id });

	b.HasData(new[]
	{
		new TestEntity
		{
			Id=2,
			Name = "Name1_2",
		},
		new TestEntity
		{
			Id=3,
			Name = "Name1_3",
			ParentId=2
		},
	});
});

query:

var q = dbContext.TestEntities
	.Where(x => x.Name == "Name1_3")
	.Select(x => x.Parent.Name + ">" + x.Name);

EF result (correct):

var efResult = await q.SingleAsyncEF();
/*
* SQL generated by EF Core
SELECT (t0."Name" || '>') || t."Name"
FROM "TestEntities" AS t
LEFT JOIN "TestEntities" AS t0 ON t."ParentId" = t0."Id"
WHERE t."Name" = 'Name1_3'
LIMIT 2
*/

// Prints: Name1_2>Name1_3
Console.WriteLine("EF result: " + efResult);

linq2db.EntityFrameworkCore result (incorrect):

var l2dbResult = await q.SingleAsyncLinqToDB();

var lq = q.ToLinqToDB();
/* SQL generated by linq2db
SELECT
		"a_Parent"."Name",
		x."Name"
FROM
		"TestEntities" x
		-- !!! Error on next line !!!!
				LEFT JOIN "TestEntities" "a_Parent" ON x."Id" = "a_Parent"."ParentId"
WHERE
		x."Name" = 'Name1_3'
LIMIT $1
*/
// Prints: ">Name1_3"
Console.WriteLine("L2DB result: " + l2dbResult);

Test project attached to current issue:

TestAppToSend.zip

Not logging generated sql

Hi, I'm not sure is that by design or not but no sql is being logged.
For example, then request to web app starts some of queries are executed using EF Context, and some with linq2db extensions over EF Context, so the latter queries not logged.
Probably something needs to be setup?

Console logging with PomeloMySql

Hello,

I have a working query logging for EF, but my recursive cte query with linq2db doesn't gets logged.

This is my appsettings.json (this is all log config as far as I know):

"Logging": {
    "LogLevel": {
      "Microsoft.EntityFrameworkCore.Database.Command": "Information"
    }
  }

How can I turn on console logging?

Insert doesn't send pk column

Hi,

After migrating from EF to Linq2db.EntityFramework everything worked as expected,
but I wanted to migrate DML also to Linq2Db, so that I could eventually remove EF completely.

From some reason, insert doesn't work.
I have some simple table :

[Table("...", Schema = "...")]
public class NaseljenoMjestoEntity
	{
		[Key]
		public int? NaseljenoMjestoId { get; set; }

		[Required]
		public string Naziv { get; set; }

               ...
        }

I've used this code to try to insert:

using (var context = _dbContext.CreateLinqToDbConnection())
			{
			    var result= context.Insert(entity);
			}

but it doesn't work.
Query generated for insert contains all columns except NaseljenoMjestoId, so naturally, it throws Cannot insert the value NULL into column 'NaseljenoMjestoId'...

NaseljenoMjestoId is Nullable, but changing it to int doesn't change anything.

We have more than 1000 entities, so I was hoping to reuse EF annotations so that I wouldn't have to regenerate all the entities (most of them have some kind of custom modifications).
It's ease to replace Key to PrimaryKey, but ForeignKey attribute doesn't have 'OtherKey' part, so it would be tedious to try to manually replace all ForeignKeys to Association.

What am I doing wrong?
Is this use case event possible (to create DataConnection from DbContext and do insert, based on EF annotations)?

I'm using linq2db.entityframeworkcore 3.0.0

Also, what is the difference between DataConnection and DataContext?
What are different use cases for both of them?

in sql case when then how to convert to linq

I'm here againใ€‚ใ€‚ใ€‚ใ€‚ใ€‚

SELECT (ISNULL(SUM(CASE WHEN oi.SaleWay='A' THEN ABS(oi.SalePrice*oi.SaleQnty) END),0) - 
        ISNULL(SUM(CASE WHEN oi.SaleWay='B' THEN ABS(oi.SalePrice*oi.SaleQnty) END),0) 
 ) AS FlowAmount FROM OrderInfo oi
LEFT JOIN (SELECT GoodsCode,GoodsLevelId FROM GoodsInfo) gi ON oi.GoodsCode = gi.GoodsCode

If you have detailed documentation, I can go seeใ€‚

How can I write this part of the code?

i want .

DECLARE @beginTime DateTime2
SET     @beginTime = '2018-07-01T00:00:00'
DECLARE @endTime DateTime2
SET     @endTime = '2018-08-01T00:00:00'
DECLARE @p1 NVarChar(4000) -- String
SET     @p1 = N'8011'

SELECT
	Sum([t3].[RechargeAmount]) as [c1],
	[t1].[GoodsBrandCode],
	Sum([t3].[RechargeQty]) as [c2]
FROM
	[MemberTendRechargeOrderDetails] [t3]
		left JOIN [GoodsInfo]  [t1] on t3.GoodsCode=t1.GoodsCode
		LEFT JOIN  [MemberTendRechargeOrder][t2]
		 ON [t2].RechargeNo = [t3].RechargeNo
WHERE
	[t2].[RechargeDate] > @beginTime AND [t2].[RechargeDate] < @endTime AND
	[t2].[SaleEmpCode] = @p1
GROUP BY
	[t1].[GoodsBrandCode]

i wirte this code

using (var Db = new HYWCRMContext(ConnectionString, loggerFactory))
{
    Db.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
    LinqToDBForEFTools.Implementation = new MyImplDefault();
    var tempQry1 =
        from gi in Db.GoodsInfo
        from mtro in Db.MemberTendRechargeOrder
        from mtrod in Db.MemberTendRechargeOrderDetails
                .LeftJoin(m => m.RechargeNo == mtro.RechargeNo).LeftJoin(m => m.GoodsCode == gi.GoodsCode)
        where mtro.RechargeDate > beginTime && mtro.RechargeDate < endTime 
        select new { mtro, mtrod,gi };

    if (!string.IsNullOrWhiteSpace(goodsCategoryCode))
    {
        tempQry1 = tempQry1.Where(m => m.gi.GoodsCategoryCode.Substring(0, 2) == goodsCategoryCode);
    }

    if (!string.IsNullOrWhiteSpace(empCodes[2]))
    {
        tempQry1 = tempQry1.Where(m => m.mtro.SaleEmpCode == empCodes[2]);
    }

    var depositQry =
        from a in tempQry1
        group a.mtrod by a.gi.GoodsBrandCode into g
        select new
        {
            SaleAmout = g.Sum(m => m.RechargeAmount),
            GoodsBrandCode = g.Key,
            SaleQnty = g.Sum(m => m.RechargeQty),
        };

    var list = depositQry.ToLinqToDB().ToList();
}

it's generated sql

DECLARE @beginTime DateTime2
SET     @beginTime = '2018-07-01T00:00:00'
DECLARE @endTime DateTime2
SET     @endTime = '2018-08-01T00:00:00'
DECLARE @p1 NVarChar(4000) -- String
SET     @p1 = N'8011'

SELECT
	Sum([t2].[RechargeAmount]) as [c1],
	[t3].[GoodsBrandCode],
	Sum([t2].[RechargeQty]) as [c2]
FROM
	[GoodsInfo] [t3]
		CROSS JOIN [MemberTendRechargeOrder] [t1]
		LEFT JOIN (
			SELECT
				[m1].[RechargeAmount],
				[m1].[RechargeQty],
				[m1].[GoodsCode]
			FROM
				[MemberTendRechargeOrderDetails] [m1]
			WHERE
				[m1].[RechargeNo] = [t1].[RechargeNo]
		) [t2] ON [t2].[GoodsCode] = [t3].[GoodsCode]
WHERE
	[t1].[RechargeDate] > @beginTime AND [t1].[RechargeDate] < @endTime AND
	[t1].[SaleEmpCode] = @p1
GROUP BY
	[t3].[GoodsBrandCode]

and throw this exception

Exception: System.Data.SqlClient.SqlException
Message  : ๆ— ๆณ•็ป‘ๅฎš็”ฑๅคšไธช้ƒจๅˆ†็ป„ๆˆ็š„ๆ ‡่ฏ†็ฌฆ "t1.RechargeNo"ใ€‚

ๆˆ‘่ฏฅๆ€Žไนˆๅ†™่ฟ™้ƒจๅˆ†ไปฃ็ ใ€‚
How can I write this part of the code?

Custom structure wrapper + == + nullable + compare => exception

  1. We have custom structure type
    public readonly struct Id<TEntity, TKey> : IEquatable<Id<TEntity, TKey>> where TEntity : IEntity<TKey>
    {
        public Id(TKey id) => Value = id;
        public TKey Value { get; }
        public static implicit operator TKey(Id<TEntity, TKey> id) => id.Value;
        public override string ToString() => Value?.ToString();
        public bool Equals(Id<TEntity, TKey> other) => EqualityComparer<TKey>.Default.Equals(Value, other.Value);
        public override bool Equals(object obj) => obj is Id<TEntity, TKey> other && Equals(other);
        public override int GetHashCode() => EqualityComparer<TKey>.Default.GetHashCode(Value);
    }
  1. We use special EF converter Id<TEntity, TKey> - TKey
  2. We use queries like this
            if (!measureUnitId.HasValue) return null;

            var workTypePermanentId = Guid.Parse(Consts.DefaultWorkTypePermanentId);
            var work = await (from w in _works
                join wT in _objects on w.WorkTypePermanentId equals wT.PermanentId
                where wT.PermanentId == workTypePermanentId
                      && !w.IsDeleted
                      && w.MeasureUnitId == measureUnitId
                      && w.IsMain
                      && w.Name.ToLower() == excelEntity.ะะฐะธะผะตะฝะพะฒะฐะฝะธะตะ’ะธะดะพะฒะ ะฐะฑะพั‚.ToLower().Trim()
                select w).FirstOrDefaultAsync().ConfigureAwait(false);
  1. We have added equality operators to Id<>
        public static bool operator == (Id<TEntity, TKey> left, Id<TEntity, TKey> right) 
            => EqualityComparer<TKey>.Default.Equals(left.Value, right.Value);
        public static bool operator != (Id<TEntity, TKey> left, Id<TEntity, TKey> right) => !(left == right);
  1. ... and got an exception
System.InvalidCastException: Can't write CLR type Intelkon.Core.Id`2[Intelkon.Erp.Storage.MeasureUnit,System.Int64] with handler type Int64Handler
  at at lambda_method(Closure , NpgsqlTypeHandler , Object , NpgsqlLengthCache& , NpgsqlParameter )
  1. Workaround 1: remove equality operators from Id<>
  2. Workaround 2: don't use equality operator for Id<> and Id<>? in linq2db queries
           if (!measureUnitId.HasValue) return null;
            var m = measureUnitId.Value;

            var workTypePermanentId = Guid.Parse(Consts.DefaultWorkTypePermanentId);
            var work = await (from w in _works
                join wT in _objects on w.WorkTypePermanentId equals wT.PermanentId
                where wT.PermanentId == workTypePermanentId
                      && !w.IsDeleted
                      && w.MeasureUnitId == m
                      && w.IsMain
                      && w.Name.ToLower() == excelEntity.ะะฐะธะผะตะฝะพะฒะฐะฝะธะตะ’ะธะดะพะฒะ ะฐะฑะพั‚.ToLower().Trim()
                select w).FirstOrDefaultAsync().ConfigureAwait(false);

the subtraction has no operation with three params

using (var db = new HYWCRMContext(ConnectionString))
{
    db.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;

    var grossProfitQry = from oi in db.OrderInfo
        from gi in db.GoodsInfo.LeftJoin(g => g.GoodsCode == oi.GoodsCode)
        where oi.OrderStatus == 0 && oi.MemberCardId == "0415955923793" && oi.SaleDate >= beginTime
        group new { oi, gi } by Sql.DatePart(Sql.DateParts.Month, oi.SaleDate) into g
        select new
        {
            Month = g.Key,
            A = g.Sum(m => m.oi.SaleWay == "A" ? m.oi.SaleMoney - m.oi.SaleQnty * Sql.Round(m.gi.SchemePrice, 2) : 0) 
                - g.Sum(m => m.oi.SaleWay == "B" ? m.oi.SaleMoney - Sql.Abs(m.oi.SaleQnty) * Sql.Round(m.gi.SchemePrice, 2) : 0) ?? 0
                - Sql.Abs(g.Sum(m => m.oi.SaleWay == "C" ? m.oi.SaleMoney - m.oi.SaleQnty * Sql.Round(m.gi.SchemePrice, 2) : 0)) ?? 0
        };
    var flowList = grossProfitQry.ToLinqToDB().ToList();
    ConsoleList(flowList);

    var tempgrossProfitQry = from oi in db.OrderInfo
        from gi in db.GoodsInfo.LeftJoin(g => g.GoodsCode == oi.GoodsCode)
        where oi.OrderStatus == 0 && oi.MemberCardId == "0415955923793" && oi.SaleDate >= beginTime
        group new { oi, gi } by Sql.DatePart(Sql.DateParts.Month, oi.SaleDate) into g
        select new
        {
            Month = g.Key,
            A = g.Sum(m => m.oi.SaleWay == "A" ? m.oi.SaleMoney - m.oi.SaleQnty * Sql.Round(m.gi.SchemePrice, 2) : 0) ??0,
            B = g.Sum(m => m.oi.SaleWay == "B" ? m.oi.SaleMoney - Sql.Abs(m.oi.SaleQnty) * Sql.Round(m.gi.SchemePrice, 2) : 0) ?? 0,
            C = Sql.Abs(g.Sum(m => m.oi.SaleWay == "C" ? m.oi.SaleMoney - m.oi.SaleQnty * Sql.Round(m.gi.SchemePrice, 2) : 0)) ?? 0
        };
    var temp = tempgrossProfitQry.ToLinqToDB().ToList();
    ConsoleList(temp);
}

result
image

It seems that in the first query, the subtraction has no operation.

about fromsql

I use linq2db.EntityFrameworkCore in a class, then i can not use Db.Query<T>().FromSql("sql");
FromSql method in Microsoft.EntityFrameworkCore;
What's the better solution?

Sql Function Translation Issues

Thanks for maintaining this library, I just started using it yesterday and am a little bit in disbelief at how easy it was to drop into an EFCore Project.

I'm working with SqlServer Json functionality and hit a few issues with dbfunctions.

  1. It appears .ToLinqToDB() doesn't pick up functions that are mapped via expression.

This does not work, it renders with the name "JsonValue":

modelBuilder.HasDbFunction(typeof(DbJson).GetMethod(nameof(DbJson.JsonValue)))
                .HasTranslation(e => SqlFunctionExpression.Create(
                    "JSON_VALUE", e, typeof(string), null));

This does work, so I do have a workaround for now since my method signature didn't actually need to be mapped:

modelBuilder.HasDbFunction(typeof(DbJson).GetMethod(nameof(DbJson.JsonValue))).HasName("JSON_VALUE");
// --- other file
[Expression("JSON_VALUE({column},{path})", ServerSideOnly = true)]
public static string JsonValue(string column, [NotParameterized] string path)
{
    throw new NotSupportedException();
}
  1. I don't know if there is interplay between mapping functions using Sql.ExpressionAttribute / Sql.FunctionAttribute / Sql.ExtensionsAttribute, but I first tried to fix it by adding those to the method, and they appear to do nothing if you put them on a method that the DbContext is already mapping, but I was expecting them to override the normal DbContext behavior.

  2. The NotParameterized attribute from EfCore appears to not be respected:

public static string JsonValue(string column, [NotParameterized] string path)
{
    throw new NotSupportedException();
}

renders to sql like

JSON_VALUE([a_Product].[Json], @path_1)

but I read it is important that the "path" argument doesn't get parameterized so that the query optimizer will to use computed Json indexes. If you have any ideas on a workaround that could force rendering it like

JSON_VALUE([a_Product].[Json], N'Actual String Value Of "path"')

please let me know because this one has me stumped.

Integration with EF Core 3.1 and Pomelo Provider failed

Hi,

I am testing out this package for the integration between EF Core and linq2db, but can't seem to get it working.

I have attached my test project below.

        [HttpGet]
        public async Task<IActionResult> Test3()
        {
            LinqToDBForEFTools.Initialize();
            // testing simple linq2db
            var students = await _context.Students.ToLinqToDBTable().ToListAsync();
            return Json(students);
        }

On my sample method above in HomeController.cs, I am expecting the above to yield the student listing to me via linq2db. But I got this exception instead.
TypeLoadException: Could not load type 'MySqlConnector.MySqlConnection' from assembly 'MySqlConnector, Version=0.69.9.0, Culture=neutral, PublicKeyToken=d33d3e53aa5f8c92'. System.Reflection.RuntimeAssembly.GetType(QCallAssembly assembly, string name, bool throwOnError, bool ignoreCase, ObjectHandleOnStack type, ObjectHandleOnStack keepAlive, ObjectHandleOnStack assemblyLoadContext) System.Reflection.RuntimeAssembly.GetType(string name, bool throwOnError, bool ignoreCase) System.Reflection.Assembly.GetType(string name, bool throwOnError) LinqToDB.DataProvider.MySql.MySqlProviderAdapter+MySqlConnector.CreateAdapter() LinqToDB.DataProvider.MySql.MySqlProviderAdapter.GetInstance(string name) LinqToDB.DataProvider.MySql.MySqlDataProvider..ctor(string name, MappingSchema mappingSchema) LinqToDB.DataProvider.MySql.MySqlDataProvider..ctor(string name) LinqToDB.EntityFrameworkCore.LinqToDBForEFToolsImplDefault.CreateLinqToDbDataProvider(EFProviderInfo providerInfo, LinqToDBProviderInfo provInfo, EFConnectionInfo connectionInfo) LinqToDB.EntityFrameworkCore.LinqToDBForEFToolsImplDefault+<>c__DisplayClass4_0.<GetDataProvider>b__0(ProviderKey k) System.Collections.Concurrent.ConcurrentDictionary<TKey, TValue>.GetOrAdd(TKey key, Func<TKey, TValue> valueFactory) LinqToDB.EntityFrameworkCore.LinqToDBForEFToolsImplDefault.GetDataProvider(EFProviderInfo providerInfo, EFConnectionInfo connectionInfo) LinqToDB.EntityFrameworkCore.LinqToDBForEFTools.GetDataProvider(EFProviderInfo info, EFConnectionInfo connectionInfo) LinqToDB.EntityFrameworkCore.LinqToDBForEFTools.CreateLinqToDbContext(DbContext context, IDbContextTransaction transaction) LinqToDB.EntityFrameworkCore.LinqToDBForEFTools.ToLinqToDBTable<T>(DbSet<T> dbSet)

Am i missing something? Or does it seem like there's a fundamental difference in MySqlConnector version used? Latest Pomelo release as of the reporting of this issue does not support 1.0 and above, but it seems like this package assumes MySqlConnector v1.0 and above.

NetCore31WebApp.zip

No way to disable change tracking?

In LinqToDBForEfTools.cs there is this code:

public static bool EnableChangeTracker 
{ 
	get => Implementation.EnableChangeTracker;
	set => Implementation.EnableChangeTracker = true;
}

But the default implementation seems to default to true already, so the only way to disable the change tracking seems to be to go through Implementation.EnableChangeTracker myself.

I'm also not sure the change tracking is properly disabled when this property is set to true, but AsNoTracking() is used on the query. It seems to still track changes in that scenario.

Using EF Core type converters

Current version don't support EF Core type converters.
I have to write each converter twice

  1. EF Core for migrations
  2. Linq2db for queries

Any plans to support EF Core 3?

Hi!

I've been using this excellent lib to complement EF Core with great results. Now that EF Core 3 is out, it'd be great to upgrade so I did some tests but unfortunately LinqToDB integration is broken due to the changes of EF Core's internals.

I made a quick attempt at fixing the lib but I realized those changes were pretty extensive.

Do you have any plans to upgrade the integration lib anytime soon?

Best regards

enum doesn't work with npgsql on bulkcopy

when trying to bulk copy a list of entities containing Enum parameters (that are represented by enum in postgres) i'm getting this message. (here for the enum currency)

Npgsql.PostgresException (0x80004005): 42804: column "currency" is of type currency but expression is of type integer
   at void Npgsql.NpgsqlConnector+<>c__DisplayClass160_0+<<DoReadMessage>g__ReadMessageLong|0>d.MoveNext()
   at void Npgsql.NpgsqlConnector+<>c__DisplayClass160_0+<<DoReadMessage>g__ReadMessageLong|0>d.MoveNext()
   at async Task<bool> Npgsql.NpgsqlDataReader.NextResult(bool async, bool isConsuming)
   at bool Npgsql.NpgsqlDataReader.NextResult()
   at async ValueTask<NpgsqlDataReader> Npgsql.NpgsqlCommand.ExecuteReaderAsync(CommandBehavior behavior, bool async, CancellationToken cancellationToken)
   at async Task<int> Npgsql.NpgsqlCommand.ExecuteNonQuery(bool async, CancellationToken cancellationToken)
   at int Npgsql.NpgsqlCommand.ExecuteNonQuery()
   at int LinqToDB.Data.DbCommandProcessor.DbCommandProcessorExtensions.ExecuteNonQueryExt(IDbCommand cmd)
   at int LinqToDB.Data.DataConnection.ExecuteNonQuery(IDbCommand command)
   at int LinqToDB.Data.DataConnection.ExecuteNonQuery()
   at int LinqToDB.Data.CommandInfo.Execute()
   at int LinqToDB.Data.DataConnectionExtensions.Execute(DataConnection connection, string sql, DataParameter[] parameters)
   at bool LinqToDB.DataProvider.MultipleRowsHelper.Execute()
   at BulkCopyRowsCopied LinqToDB.DataProvider.BasicBulkCopy.MultipleRowsCopy1(MultipleRowsHelper helper, IEnumerable source)
   at BulkCopyRowsCopied LinqToDB.DataProvider.BasicBulkCopy.MultipleRowsCopy1<T>(ITable<T> table, BulkCopyOptions options, IEnumerable<T> source)
   at BulkCopyRowsCopied LinqToDB.DataProvider.PostgreSQL.PostgreSQLBulkCopy.MultipleRowsCopy<T>(ITable<T> table, BulkCopyOptions options, IEnumerable<T> source)
   at BulkCopyRowsCopied LinqToDB.DataProvider.BasicBulkCopy.BulkCopy<T>(BulkCopyType bulkCopyType, ITable<T> table, BulkCopyOptions options, IEnumerable<T> source)
   at BulkCopyRowsCopied LinqToDB.DataProvider.PostgreSQL.PostgreSQLDataProvider.BulkCopy<T>(ITable<T> table, BulkCopyOptions options, IEnumerable<T> source)
   at BulkCopyRowsCopied LinqToDB.Data.DataConnectionExtensions.BulkCopy<T>(DataConnection dataConnection, BulkCopyOptions options, IEnumerable<T> source)
   at BulkCopyRowsCopied LinqToDB.EntityFrameworkCore.LinqToDBForEFTools.BulkCopy<T>(DbContext context, BulkCopyOptions options, IEnumerable<T> source)
  Exception data:
    Severity: ERROR
    SqlState: 42804
    MessageText: column "currency" is of type currency but expression is of type integer
    Hint: You will need to rewrite or cast the expression.
    Position: 832
    File: parse_target.c
    Line: 591
    Routine: transformAssignedExpr

what about Transactions?

Hello,

I want to wrap in transaction 2 bulkCopy using linq2db.EntityFrameworkCore.
How can I do it?

I tried, with EF db context as DbContext:

DbContext.BeginTransaction(); // method not found
var l2db = DbContext.CreateLinqToDbContext(); 
l2db.BeginTransaction(); // method not found

I use namespaces:

using LinqToDB;
using LinqToDB.Data;
using LinqToDB.EntityFrameworkCore;

Community Question before release

In upcoming release (few days).
I have implemented ChangeTracker support and incomparable in quality Global Query Filters support.

Question is: Should i enable ChangeTracker support by default?
All standard ways of disabling ChangeTracker (AsNoTracking and ChangeTracker.QueryTrackingBehavior == QueryTrackingBehavior.NoTracking) should work.

Inheritance TPH with HasDiscriminator doesn't work

FYI : I noticed TPH doesn't work well with BulkCopy https://github.com/NosCoreIO/NosCore.Dao/blob/52480cab1ca7bbf3244663441603a4bcbf82b911/src/NosCore.Dao/Dao.cs#L145

the dbcontext https://github.com/NosCoreIO/NosCore.Dao/blob/master/test/NosCore.Dao.Tests/Database/NosCoreContext.cs

when running the tests i'm getting "NOT NULL constraint failed: CompositeTphBaseEntity.Discriminator"

i don't think TPH is widely used anyway but seems to be one of the current limitation of this library

[Question] Fast Eager Loading (incomparable faster on massive Include query)

Hi there. In my project we have quite a lot of includes when querying items from database. After switching one of internal projects to .netcore3.1 we had to refactor a little bit every query to have fewer includes and then also use LoadAsync() this is horrible and painful.

I just wanted to ask "how many includes this lib can handle?". Don't get me wrong but we have like 22 includes (I've just counted includes (but there are more with ThenInclude() - I've just gave a general number of main includes) and it seems the app hangs out at generating db query for few minutes now...

I know the number of includes is ridiculous but please... don't judge :) There are more than 40ppl working on those projects and quality is not always the thing.

updateAsync throw exception

try
{
    LinqToDBForEFTools.Initialize();
    //ๆ›ดๆ–ฐ
    var effectRows = await db.MemberExpand.Where(m => m.MemberCardId == request.MemberCardId)
        .Set(m => m.BabyMonthAge, memberExpand.BabyMonthAge)
        .Set(m => m.RechargeAmount, memberExpand.RechargeAmount)
        .Set(m => m.ReceiveAmount, memberExpand.ReceiveAmount)
        .Set(m => m.ConsumeCoodsBrand, memberExpand.ConsumeCoodsBrand)
        .Set(m => m.ConsumeCoodsCategory, memberExpand.ConsumeCoodsCategory)
        .Set(m => m.TotalStoredConsumeAmount, memberExpand.TotalStoredConsumeAmount)
        .Set(m => m.TotalStoredRechargeAmount, memberExpand.TotalStoredRechargeAmount)
        .Set(m => m.LastConsumeDate, memberExpand.LastConsumeDate)
        .Set(m => m.LastVisitDate, memberExpand.LastVisitDate)
        .Set(m => m.LastUpdateTime, memberExpand.LastUpdateTime)
        .Set(m => m.TotalConsumeAmount, memberExpand.TotalConsumeAmount)
        .Set(m => m.TotalConsumeOrder, memberExpand.TotalConsumeOrder)
        .Set(m => m.CustomerPrice, memberExpand.CustomerPrice)
        .UpdateAsync(cancellationToken);
    _logger.LogInformation($"ๆ›ดๆ–ฐไผšๅ‘˜ๆ‰ฉๅฑ•่กจๅ—ๅฝฑๅ“่กŒๆ•ฐ๏ผš{effectRows}");
}
catch (Exception e)
{
    _logger.LogError(e, $"ไผšๅ‘˜ๆ‰ฉๅฑ•่กจ{oper}ๅคฑ่ดฅ");
    return false;
}
 System.ArgumentException: Parameter 'expression' is a 'LinqToDB.Linq.IUpdatable`1[Hyw.Data.MemberExpand]', which cannot be assigned to type 'System.Collections.Generic.IEnumerable`1[Hyw.Data.MemberExpand]'.
Parameter name: expression
   at Remotion.Utilities.ArgumentUtility.CheckTypeIsAssignableFrom(String argumentName, Type actualType, Type expectedType)
   at Remotion.Linq.QueryableBase`1..ctor(IQueryProvider provider, Expression expression)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.CreateQuery[TElement](Expression expression)
   at LinqToDB.LinqExtensions.Set[T,TV](IQueryable`1 source, Expression`1 extract, TV value) in C:\projects\linq2db\Source\LinqToDB\LinqExtensions.cs:line 877
   at Hyw.CommandHandlers.MemberExpandCreateOrUpdateCommandHandler.Handle(MemberExpandCreateOrUpdateCommand request, CancellationToken cancellationToken) in D:\VsProjects\Hyw2\src\Hyw.CommandHanders\MemberExpandCreateOrUpdateCommandHandler.cs:line 165|url: |action: 
2018-12-06 15:45:53.1325||INFO|Hyw.CommandHandlers.MemberExpandCreateOrUpdateCommandHandler|ไผšๅ‘˜ๆ‰ฉๅฑ•่กจ,ๆ“ไฝœ๏ผšๆ›ดๆ–ฐ๏ผŒ DATA:{"ExpandId":0,"MemberCardId":"0115202151325","StarScore":0.0,"TotalConsumeAmount":68.0000,"TotalConsumeOrder":2.0,"CustomerPrice":34.0000,"OrderSalesAmount":68.0000,"RechargeAmount":0.0,"ReceiveAmount":0.0,"TotalStoredRechargeAmount":0.0,"TotalStoredConsumeAmount":0.0,"LastConsumeDate":"2018-08-20T16:01:28","LastVisitDate":"0001-01-01T00:00:00","CreateTime":"2018-12-06T15:45:53.1325086+08:00","LastUpdateTime":"2018-12-06T15:45:53.1325115+08:00","LastUpdateRemark":"","ConsumeCoodsBrand":"d2,PP","ConsumeCoodsCategory":"้›ถ้ฃŸ-ๆžœไป™ๅคš็ปด,ๆณจๅ†Œไผšๅ‘˜,็”จๅ“็ฑป","BabyMonthAge":27} |url: |action: 

Where did I write wrong?

[Question] Correct resources cleanup

Hi,

Please help me understand, how does linq2db.EntityFrameworkCore integration cleans up created DataConnection? I see that extensions methods, e.g. ToLinqToDB(), create a linqToDb DataConnection which is IDisposable, but seems like created DataConnection not being diposed and thus connection or command could leak.
Am I wrong? Does the integration fully relies on EF Core's connection management?

Thanks

Crash when enum type is byte

I'm receiving a crash when there is an enum of a byte type in the entity model. I wasn't receiving these types of crashes in 2.0.0 version.

The exception type is:
System.Reflection.AmbiguousMatchException: 'Ambiguous match found.'

Very simply the problem could be narrowed down as follows

class Program
{
    public enum CrashMe : byte
    {
        One = 1,
        Two = 2
    }
    static void Main(string[] args)
    {
        typeof(Decimal).GetConstructorEx(new[] { typeof(CrashMe) });
    }
}

I'm also attaching a repro-project
EnumRepro.zip

I'm aware that this issue might go down to L2DB core, however I'm opening it here as there wasn't such problem with the 2.0.0 version [if you downgrade the package version in the repro project to 2.0.0. this problem disappears]

select one to many how to write

my code

                          from emp in db.EmployeeInfo
                          from branch in db.BranchInfo
                          from att in (
                              from attach in db.Attachment
                              where attach.Type == 1 && attach.Status == 0 && attach.ItemId == emp.EmpId
                              group attach by attach.ItemId into g
                              select new
                              {
                                  EmpId  =g.Key,
                                  EmpPic = g.Select(m=>m.Url).AsQueryable(),
                              })
                          where emp.EmpCode == "1002" && emp.Status == 0 && emp.BranchCode == branch.BranchCode
                          select new EmployeeOutput
                          {
                              EmpAvatar = emp.EmpAvatar,
                              EmpCode = emp.EmpCode,
                              EmpId = emp.EmpId,
                              EmpName = emp.EmpName,
                              EmpPhone = emp.EmpPhone,
                              EmpPic = att.EmpPic.ToList(),
                              BranchAddress = branch.BranchAddress,
                              BranchName = branch.BranchName
                          };
                var temp = qry.ToLinqToDB().FirstOrDefault();

translate sql

SELECT TOP (1)
	[t4].[EmpAvatar],
	[t4].[EmpCode],
	[t4].[EmpId],
	[t4].[EmpName],
	[t4].[EmpPhone],
	[t3].[c1] as [c11],
	[t1].[BranchAddress],
	[t1].[BranchName]
FROM
	[EmployeeInfo] [t4]
		CROSS JOIN [BranchInfo] [t1]
		CROSS APPLY (
			SELECT
				(
					SELECT
						[keyParam].[Url]
					FROM
						[Attachment] [keyParam]
					WHERE
						[t2].[ItemId] = [keyParam].[ItemId] AND
						[keyParam].[Type] = 1 AND
						[keyParam].[Status] = 0 AND
						[keyParam].[ItemId] = [t4].[EmpId]
				) as [c1]
			FROM
				[Attachment] [t2]
			WHERE
				[t2].[Type] = 1 AND [t2].[Status] = 0 AND [t2].[ItemId] = [t4].[EmpId]
			GROUP BY
				[t2].[ItemId]
		) [t3]
WHERE
	[t4].[EmpCode] = N'1002' AND [t4].[Status] = 0 AND
	[t4].[BranchCode] = [t1].[BranchCode]

error .
image

ๅญๆŸฅ่ฏข่ฟ”ๅ›ž็š„ๅ€ผไธๆญขไธ€ไธชใ€‚ๅฝ“ๅญๆŸฅ่ฏข่ทŸ้šๅœจ =ใ€!=ใ€<ใ€<=ใ€>ใ€>= ไน‹ๅŽ๏ผŒๆˆ–ๅญๆŸฅ่ฏข็”จไฝœ่กจ่พพๅผๆ—ถ๏ผŒ่ฟ™็งๆƒ…ๅ†ตๆ˜ฏไธๅ…่ฎธ็š„ใ€‚

linq2db.EntityFrameworkCore with 3.0.0.preview2

Is it possible to use it with 3.0.0.preview2?
It used to work with 2.9.7, but now it throws:

System.MissingMethodException: 'Method not found: 'Boolean LinqToDB.DataProvider.IDataProvider.IsCompatibleConnection(System.Data.IDbConnection)'.'

when I call

source.ToLinqToDB()

I have over 1.5k classes so I can't just swap all of them at the same time.
That is why I've tried to use this adapter as a intermediate solution.

Problems with Left Outer Join

Hello,

left join not generate with EF context
exception error:

Method 'Boolean IsDBNull(Int32)' declared on type 'System.Data.IDataRecord' cannot be called with instance of type 'System.Boolean'

my model:

    public partial class Devtypes
    {
        public int Devtypeid { get; set; }
        public string Typename { get; set; }
        public int GlobalType { get; set; }
    }

    public partial class Devices
    {
        public Guid Devid { get; set; }
        public string Sernum { get; set; }
        public int Devtypeid { get; set; }
    }   

Context

public partial class IssueContext : DbContext
 {
        public IssueContext()  {  }
        public IssueContext(DbContextOptions<IssueContext> options)
            : base(options)   {  }

        public virtual DbSet<Devices> Devices { get; set; }
        public virtual DbSet<Devtypes> Devtypes { get; set; }
}

Error code

using (var l2db = db.CreateLinqToDbConnection())
{
     LinqToDB.Common.Configuration.Linq.GenerateExpressionTest = true;
                    var test =
                        from dt in l2db.GetTable<Devtypes>()
                        from d in l2db.GetTable<Devices>().LeftJoin(pr => pr.Devtypeid == dt.Devtypeid)
                        select new { dt, d }
                           ;

      var x0 = test.ToList();

 }

this code throw exception:

{
	"ClassName": "System.ArgumentException",
	"Message": "Method 'Boolean IsDBNull(Int32)' declared on type 'System.Data.IDataRecord' cannot be called with instance of type 'System.Boolean'",
	"StackTraceString": "at System.Linq.Expressions.Expression.ValidateCallInstanceType(Type instanceType, MethodInfo method)
					   at System.Linq.Expressions.Expression.ValidateStaticOrInstanceMethod(Expression instance, MethodInfo method)
					   at System.Linq.Expressions.Expression.ValidateMethodAndGetParameters(Expression instance, MethodInfo method)
					   at System.Linq.Expressions.Expression.Call(Expression instance, MethodInfo method, Expression arg0)
					   at System.Linq.Expressions.Expression.Call(Expression instance, MethodInfo method, IEnumerable`1 arguments)
					   at LinqToDB.EntityFrameworkCore.EFCoreMetadataReader.<>c__DisplayClass6_0.<GetDbFunctionFromMethodCall>b__0(MemberInfo mi)
					   at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
					   at LinqToDB.EntityFrameworkCore.EFCoreMetadataReader.GetAttributes[T](Type type, MemberInfo memberInfo, Boolean inherit)
					   at System.Linq.Enumerable.<SelectManyIterator>d__167`3.MoveNext()
					   at System.Collections.Generic.LargeArrayBuilder`1.AddRange(IEnumerable`1 items)
					   at System.Collections.Generic.EnumerableHelpers.ToArray[T](IEnumerable`1 source)
					   at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
					   at LinqToDB.Mapping.MappingSchema.GetAttribute[T](Type type, MemberInfo memberInfo, Boolean inherit)
					   at LinqToDB.Linq.Builder.ExpressionBuilder.UpdateNullabilityFromExtension(Expression resultExpr)
					   at LinqToDB.Expressions.Extensions.Transform(Expression expr, Func`2 func)
					   at LinqToDB.Expressions.Extensions.Transform(Expression expr, Func`2 func)
					   at LinqToDB.Linq.Builder.ExpressionBuilder.ConvertAssignmentArgument(IBuildContext context, Expression expr, MemberInfo memberInfo, Boolean enforceServerSide, String alias)
					   at LinqToDB.Linq.Builder.ExpressionBuilder.TransformExpression(IBuildContext context, Expression expr, Boolean enforceServerSide, String alias)
					   at LinqToDB.Linq.Builder.ExpressionBuilder.<>c__DisplayClass77_0.<BuildExpression>b__0(Expression expr)
					   at LinqToDB.Expressions.Extensions.Transform(Expression expr, Func`2 func)
					   at LinqToDB.Linq.Builder.ExpressionBuilder.BuildExpression(IBuildContext context, Expression expression, Boolean enforceServerSide, String alias)
					   at LinqToDB.Linq.Builder.SelectContext.BuildExpression(Expression expression, Int32 level, Boolean enforceServerSide)
					   at LinqToDB.Linq.Builder.SelectContext.BuildQuery[T](Query`1 query, ParameterExpression queryParameter)
					   at LinqToDB.Linq.Builder.ExpressionBuilder.Build[T]()
					   at LinqToDB.Linq.Query`1.CreateQuery(IDataContext dataContext, Expression expr)
					   at LinqToDB.Linq.Query`1.GetQuery(IDataContext dataContext, Expression& expr)
					   at LinqToDB.Linq.ExpressionQuery`1.GetQuery(Expression& expression, Boolean cache)
					   at LinqToDB.Linq.ExpressionQuery`1.System.Collections.Generic.IEnumerable<T>.GetEnumerator()
					   at System.Collections.Generic.List`1.AddEnumerable(IEnumerable`1 enumerable)
					   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)",
	"RemoteStackIndex": 0,
	"HResult": -2147024809,
	"Source": "System.Linq.Expressions",
}

this error only appears when I use "linq2db.EntityFrameworkCore"
in linq2db with this model I got normal left join qwery
I try both Guids and Integers as primary, error is same

my enviroment:
Asp Net Core 2.2
"linq2db" Version="2.9.1"
"linq2db.EntityFrameworkCore" Version="1.7.0"
"Npgsql" Version="4.1.1"
"Npgsql.EntityFrameworkCore.PostgreSQL" Version="2.2.4"
Postgres 9.6

.ToLinq2Db() after .AsNoTracking() produce same query, but incorrect results

Steps:

  1. Use code like Details.Include(d => d.Master).AsNoTracking().ToLinq2Db().ToArray()
  2. Use code like Details.Include(d => d.Master).ToLinq2Db().AsNoTracking().ToArray()

Expected result:
resul of 1 == result of 2

Actual result:
result of 1 duplicates same master records in memory for all details

Sample:
https://github.com/Kirill-Maurin/linq2db.Sample/blob/a8c2561e379163915a4925e5a2aa91228170548f/linq2db.Sample.Tests/IdTests.cs#L140

Integration with EfCore.NetTopologySuite

Hello!
I want to use spatial data in my app and i found nothing about integration with NetTopologySuite. Do you have any plans about this feature? Or this feature exists out of the box and not documented?

If i try code like this, exception thrown:

class Point  
{  
    [Key]  
    public int Id { get; set; }
    public Geometry GeoPoint { get; set; }
}
    Geometry border = GetNtsBorder();
    List<Station> = contexts.PointDbSet.ToLinqToDBTable()
        .TableName("specificPointTable")
        .Where(x => border.Contains(x.GeoPoint)) //or intersects or something else
        .ToList();

System.ArgumentException: No mapping exists from object type NetTopologySuite.Geometries.LinearRing to a known managed provider native type.
at Microsoft.Data.SqlClient.MetaType.GetMetaTypeFromValue(Type dataType, Object value, Boolean inferLen, Boolean streamAllowed)
at Microsoft.Data.SqlClient.MetaType.GetMetaTypeFromType(Type dataType)
at Microsoft.Data.SqlClient.SqlParameter.GetMetaTypeOnly()
at Microsoft.Data.SqlClient.SqlParameter.get_SqlDbType()
at lambda_method(Closure , IDbDataParameter )
at LinqToDB.DataProvider.SqlServer.SqlServerDataProvider.SetParameter(DataConnection dataConnection, IDbDataParameter parameter, String name, DbDataType dataType, Object value)
at LinqToDB.Data.DataConnection.QueryRunner.AddParameter(DataConnection dataConnection, ICollection1 parms, String name, SqlParameter parm) at LinqToDB.Data.DataConnection.QueryRunner.GetParameters(DataConnection dataConnection, PreparedQuery pq) at LinqToDB.Data.DataConnection.QueryRunner.SetQuery(DataConnection dataConnection, IQueryContext queryContext, Int32 startIndent) at LinqToDB.Data.DataConnection.QueryRunner.SetQuery() at LinqToDB.Linq.QueryRunnerBase.SetCommand(Boolean clearQueryHints) at LinqToDB.Data.DataConnection.QueryRunner.ExecuteReader() at LinqToDB.Linq.QueryRunner.ExecuteQuery[T](Query query, IDataContext dataContext, Mapper1 mapper, Expression expression, Object[] ps, Object[] preambles, Int32 queryNumber)+MoveNext()
at System.Collections.Generic.List1..ctor(IEnumerable1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)

Thank you in advance!

[net5.0] Sequence '[Microsoft.EntityFrameworkCore.Query.QueryRootExpression]' cannot be converted to SQL

linq2db 3.1.6
linq2db.EntityFrameworkCore 5.0.2
Microsoft.EntityFrameworkCore 5.0.0
TargetFramework net5.0

var query = dbContext.SomeItems.Where(x => x.IsDeleted && x.Updated < dateTime).Take(20);

return dbContext.SomeItems
                .Where(x => query
                    .Select(y => y.PrimaryKeyStringId)
                    .Contains(x.PrimaryKeyStringId)
                )
                .ToLinqToDB()
                .DeleteAsync();
LinqToDB.Linq.LinqException : Sequence '[Microsoft.EntityFrameworkCore.Query.QueryRootExpression]' cannot be converted to SQL.
   at LinqToDB.Linq.Builder.ExpressionBuilder.ConvertSequence(BuildInfo buildInfo, ParameterExpression param, Boolean throwExceptionIfCantConvert)
   at LinqToDB.Linq.Builder.WhereBuilder.Convert(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo, ParameterExpression param)
   at LinqToDB.Linq.Builder.MethodCallBuilder.Convert(ExpressionBuilder builder, BuildInfo buildInfo, ParameterExpression param)
   at LinqToDB.Linq.Builder.ExpressionBuilder.ConvertSequence(BuildInfo buildInfo, ParameterExpression param, Boolean throwExceptionIfCantConvert)
   at LinqToDB.Linq.Builder.TakeSkipBuilder.Convert(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo, ParameterExpression param)
   at LinqToDB.Linq.Builder.MethodCallBuilder.Convert(ExpressionBuilder builder, BuildInfo buildInfo, ParameterExpression param)
   at LinqToDB.Linq.Builder.ExpressionBuilder.ConvertSequence(BuildInfo buildInfo, ParameterExpression param, Boolean throwExceptionIfCantConvert)
   at LinqToDB.Linq.Builder.ExpressionBuilder.ConvertExpressionTree(Expression expression)
   at LinqToDB.Linq.Builder.ExpressionBuilder.OptimizeExpressionImpl(Expression expr, HashSet`1 currentParameters)
   at LinqToDB.Linq.Builder.ExpressionBuilder.<>c__DisplayClass45_0.<OptimizeExpression>b__0(Expression e)
   at LinqToDB.Expressions.Extensions.Transform(Expression expr, Func`2 func)
   at LinqToDB.Linq.Builder.ExpressionBuilder.OptimizeExpression(Expression expression)
   at LinqToDB.Linq.Builder.ExpressionBuilder.ConvertSelect(MethodCallExpression method)
   at LinqToDB.Linq.Builder.ExpressionBuilder.OptimizeExpressionImpl(Expression expr, HashSet`1 currentParameters)
   at LinqToDB.Linq.Builder.ExpressionBuilder.<>c__DisplayClass45_0.<OptimizeExpression>b__0(Expression e)
   at LinqToDB.Expressions.Extensions.Transform(Expression expr, Func`2 func)
   at LinqToDB.Expressions.Extensions.Transform2[T](IEnumerable`1 source, Func`2 func)
   at LinqToDB.Expressions.Extensions.Transform(Expression expr, Func`2 func)
   at LinqToDB.Expressions.Extensions.Transform(Expression expr, Func`2 func)
   at LinqToDB.Expressions.Extensions.Transform(Expression expr, Func`2 func)
   at LinqToDB.Linq.Builder.ExpressionBuilder.OptimizeExpression(Expression expression)
   at LinqToDB.Linq.Builder.ExpressionBuilder.ConvertWhere(MethodCallExpression method)
   at LinqToDB.Linq.Builder.ExpressionBuilder.OptimizeExpressionImpl(Expression expr, HashSet`1 currentParameters)
   at LinqToDB.Linq.Builder.ExpressionBuilder.<>c__DisplayClass45_0.<OptimizeExpression>b__0(Expression e)
   at LinqToDB.Expressions.Extensions.Transform(Expression expr, Func`2 func)
   at LinqToDB.Expressions.Extensions.Transform2[T](IEnumerable`1 source, Func`2 func)
   at LinqToDB.Expressions.Extensions.Transform(Expression expr, Func`2 func)
   at LinqToDB.Linq.Builder.ExpressionBuilder.OptimizeExpression(Expression expression)
   at LinqToDB.Linq.Builder.ExpressionBuilder.ConvertExpressionTree(Expression expression)
   at LinqToDB.Linq.Builder.ExpressionBuilder..ctor(Query query, IDataContext dataContext, Expression expression, ParameterExpression[] compiledParameters)
   at LinqToDB.Linq.Query`1.CreateQuery(IDataContext dataContext, Expression expr)
   at LinqToDB.Linq.Query`1.GetQuery(IDataContext dataContext, Expression& expr)
   at LinqToDB.Linq.ExpressionQuery`1.GetQuery(Expression& expression, Boolean cache)
   at LinqToDB.Linq.ExpressionQuery`1.LinqToDB.Async.IQueryProviderAsync.ExecuteAsync[TResult](Expression expression, CancellationToken cancellationToken)
   at LinqToDB.LinqExtensions.DeleteAsync[T](IQueryable`1 source, CancellationToken token)

image

It was ok before upgrade to 5.0

Is it possible to use EF Core's DbSet<>.FromSqlRaw along with ToLinqToDB()?

I have an application that bases some result sets on raw SQL queries for an entity. The IQueryable returned from DbSet<>.FromSqlRaw("select * from tablename") for example fails when attempting to enumerate the IQueryable then returned from ToLinqToDB(). Is this situation supported? I was hoping it would use a subquery to apply the additional filters added by users of the IQueryable returned from ToLinqToDB().

I'm using linq2db.EntityFrameworkCore 2.0.5, linq2db 2.9.7, EFCore 3.1.3 against SQL Server 2017.

I receive the following exception and stack trace:

The method or operation is not implemented.
  at Microsoft.EntityFrameworkCore.RelationalQueryableExtensions.FromSqlOnQueryable[TEntity](IQueryable`1 source, String sql, Object[] parameters)
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
 at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
 at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
 at LinqToDB.EntityFrameworkCore.LinqToDBForEFToolsImplDefault.<>c__DisplayClass35_0.<TransformExpression>g__LocalTransform|2(Expression e)
 at LinqToDB.EntityFrameworkCore.LinqToDBForEFToolsImplDefault.<>c__DisplayClass35_0.<TransformExpression>b__3(Expression e)
 at LinqToDB.Expressions.Extensions.Transform(Expression expr, Func`2 func)
 at LinqToDB.EntityFrameworkCore.LinqToDBForEFToolsImplDefault.TransformExpression(Expression expression, IDataContext dc, DbContext ctx, IModel model)
 at LinqToDB.EntityFrameworkCore.LinqToDBForEFTools.TransformExpression(Expression expression, IDataContext dc, DbContext ctx, IModel model)
 at LinqToDB.EntityFrameworkCore.LinqToDBForEFToolsDataContext.ProcessExpression(Expression expression)
 at LinqToDB.Linq.Query`1.GetQuery(IDataContext dataContext, Expression& expr)
 at LinqToDB.Linq.ExpressionQuery`1.GetQuery(Expression& expression, Boolean cache)
 at LinqToDB.Linq.ExpressionQuery`1.System.Collections.Generic.IEnumerable<T>.GetEnumerator()
 at LinqToDB.EntityFrameworkCore.Internal.LinqToDBForEFQueryProvider`1.System.Collections.Generic.IEnumerable<T>.GetEnumerator()
 at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
 at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
 at Redacted.HealthCheckController.Get() in C:\redacted\HealthCheckController.cs:line 36
 at Microsoft.Extensions.Internal.ObjectMethodExecutor.Execute(Object target, Object[] parameters)
 at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.SyncObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
 at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<<InvokeActionMethodAsync>g__Logged|12_1>d.MoveNext()

I'm calling a method on my data context that does the following:

public virtual IQueryable<CapacityData> GetRunsReport()
        {
            return CapacityRows.FromSqlRaw("select * from API_CapacityData_t where ProcessUnitCode IN (200, 201, 202, 203, 204, 205, 206)");
        }

and then, and an example, doing this with that context:
_dc.GetRunsReport().ToLinqToDB().ToList();

I understand this scenario might not be intended as supported, but in the case it is supposed to be handled, I'm opening this issue.

Thank you!

Dependencies warning

warning NU1603: linq2db.EntityFrameworkCore 1.0.0 ไพ่ต–ไบŽ linq2db (>= 2.1.0-rc2453)๏ผŒไฝ†ๆ‰พไธๅˆฐ linq2db 2.1.0-rc2453ใ€‚ ๅทฒ่งฃๅ†ณ linq2db 2.1.0 ็š„่ฟ‘ไผผๆœ€ไฝณๅŒน้…ใ€‚

One-to-many projection creates many subqueries

First of all - this tool practically saved my life when migrating from EF6 to EF Core, great job, everything works better than EF Core, instead of one thing

LinqToDB.Common.Configuration.Linq.AllowMultipleQuery = true;

var querySample = db.TicketNumbers.Where(p => p.Ticket.Name == "Lacna").Select(p => new
{
    Id = p.Id,
    TicketName = p.Ticket.Name,
    CustomFields = p.CustomFieldValues.Select(cf => new
    {
        Name = cf.CustomFieldDefinition.Name,
        Value = cf.Value
    }).ToList()
}).ToLinqToDB().ToList();

This guery yields back 300 results, from the logging it seems that Linq2Db core runs the subquery for each of the obtained item. [= 300 subqueries, 300 roundtrips to the DB]. For our scenario, for example, this creates an issue as our SQL Server is physically located elsewhere than the calling app creating a huge performance gap due to the latency, but I believe this might be an issue for other scenarios too (running 301 queries when in fact only 2 are needed)

From observing the logs EF Core handles this differently - running a single subquery on the very same condition as main "root" query, effectively creating only one more roundtrip to the DB, then linking the data based on their foreign-key declaration.

To sum it up, I have 3 questions:

  • Is there anything I can do to change the one-to-many behavior?
  • Are there any plans to change the subdata loading routine?
  • If I wanted to hack a solution for our needs by changing the Linq2Db core, could you advise me where should I look?

.NETStandard 2.0 dependency

EF core is dependent on .NETStandard 2.0, allowing .net framework to use both ef core and linq2db.
Would it be possible to switch back to .NETStandard 2.0 so this great package could be used from .net framework applications too. Thanks.

how to write contains or indexof list

using (var db = new HYWCRMContext(connectionString))
{
    //this list  is param,
    var list = new string[] { "0-6", "7-9" };
    // MemberResTagNames nvarchar is '0-6,10-12'
    var temp = db.MemberInfo.Where(m => m.MemberResTagNames.IndexOf(list)>0).ToList();
}

i want this sql

SELECT * FROM  MemberInfo
WHERE (CharIndex(MemberResTagNames,'0-6')>0 OR CharIndex(MemberResTagNames,'7-9')>0) 

how to write

I actually want the higher the label coincidence, the first one.
But now I can only find the labels first.

How do I get the maximum value of one group and the minimum value of another group.

Hello

You can help me transform my query to use with linq2db.

				 TABLE 1
+------------+--------------+---------------+-------------+-----------------+
| --  Code -- | - IdGroup1 - | - IdGroup2 - | -  Client - | - NameProtocol -|
+ ------------+--------------+--------------+-------------+-----------------+
|    ZZ-100   |      11      |      22      |       1     |       OSM1      |
+ ------------+--------------+--------------+-------------+-----------------+
|    ZZ-200   |     100      |      110     |       1     |       OSM1      |
+ ------------+--------------+--------------+-------------+-----------------+
|    ZZ-300   |      500     |      550     |       1     |       OSM1      |
+------------+--------------+---------------+-------------+-----------------+
                             TABLE 3
> ---------------------+-------------------+----------------+
> --  NameProtocol  -- | -- Description -- | -- Protocol -- |
> ---------------------+-------------------+----------------+
>         ATC0         |        d1         |      UDP       |
> ---------------------+-------------------+----------------+
>         OSM1         |        d2         |      TCP       |
> ---------------------+-------------------+----------------+
                                      TABLE 2
+----------+-----------------------+----------------+----------------+--------------+
| - Level -| ------- Date -------- | -- IdGroup1 -- | -- IdGroup2 -- | -- Status -- |
+ ---------+-----------------------+----------------+----------------+--------------+
|    65    |  2020-09-16 02:30:40  |       11       |       22       |      0       |
v ---------+-----------------------+----------------+----------------+--------------+
|    70    |  2020-09-16 02:30:30  |       11       |       22       |      1       |
+ ---------+-----------------------+----------------+----------------+--------------+
|    80    |  2020-09-16 02:30:20  |       11       |       22       |      1       |
+ ---------+-----------------------+----------------+----------------+--------------+
|    100   |  2020-09-16 02:30:10  |       11       |       22       |      0       |
+ ---------+-----------------------+----------------+----------------+--------------+
|    110   |  2020-09-16 02:30:00  |       11       |       22       |      0       |
+ ---------+-----------------------+----------------+----------------+--------------+
|    650   |  2020-09-16 02:40:40  |       100      |      110       |      0       |
+ ---------+-----------------------+----------------+----------------+--------------+
|    700   |  2020-09-16 02:40:30  |       100      |      110       |      1       |
+ ---------+-----------------------+----------------+----------------+--------------+
|    800   |  2020-09-16 02:40:20  |       100      |      110       |      1       |
+ ---------+-----------------------+----------------+----------------+--------------+
|   1000   |  2020-09-16 02:50:00  |       500      |      550       |      1       |
+ ---------+-----------------------+----------------+----------------+--------------+

My query obtains the maximum or minimum value of the LEVEL field, with the following conditions and for that subqueries were resolved, which first returns the following:

  • Get the amount of Status = 0,
  • Get the amount of Status = 1,
  • Get the maximum value of LEVEL for Status = 1,
  • Get the minimum value of LEVEL for Status = 0
var dateFilter = DateTime.Parse ("2020-09-16 03:00:00");

var queryCondition = table2
                        .Where(hn => hn.Date <= dateFilter)
			.Join(table1.Where(w => (w.Client == 1)),        	
						h => new { h. IdGroup1, h. IdGroup2 }, 
						p => new { p. IdGroup1, p. IdGroup2 }, 
						(h, p) => new { h, p })                 
			.Join(table3.Where(w => (w. Protocol == "TCP")),
						pt => pt.p.NameProtocol,
						p => p. NameProtocol,
						(pt, p) => new { pt, p })
			.GroupBy(gb => new { gb.pt.h.Status, gb.pt.h.Level, gb.pt.p.code })
			.Select(s => new
					{
					Code = s.Key.code,
					Cnt_0 = (s.Key.Status == 0) ? 1 : 0,
					Cnt_1 = (s.Key.Status == 1) ? 1 : 0,
					Max_1 = (s.Key.Status == 1) ? (double?)(s.Key.Level) : (double?)null,
					Min_0 = (s.Key.Status == 0) ? (double?)(s.Key. Level) : (double?)null
						})
			.GroupBy(hn => new { hn.Code })
			.Select(g => new
					{
					Code = g.Key.Code,
					Static = g.Sum(p => p.Cnt_0),
					Dinamic = g.Sum(p => p.Cnt_1),
					MaxDinamic = (double?)(g.Max(p => p.Max_1)),
					MinStatic = (double?)(g.Min(p => p.Min_0))
					})
				.ToList();

var queryNF = queryCondition
				.OrderBy(ob => ob.Code)
				.Select(qC => new
					{
					Code = qC.Code,
					Level = qC.Static >= qC.Dinamic ? qC.MinStatic :
						qC.Static < qC.Dinamic ? qC.MaxDinamic : null
					})
				.ToList();

Entity Framework 5 Support?

EF Core 5.0 will be released this month, RC1 & RC2 are already available. I'm eager to use some new EF Core 5.0 features, but the lacking support of linq2db.EntityFrameworkCore holds me back.

From what I saw there is at least one breaking change -> Microsoft.EntityFrameworkCore.RelationalQueryableExtensions.FromSqlOnQueryable
does not longer exist. It is used in LinqToDB.EntityFrameworkCore.LinqToDBForEFToolsImplDefault.GetContextOptions.

Is anybody having a look at 5.0 compatibility? Is there maybe an ETA?

Getting error "ORA-00928" when trying to context.BulkCopy

Hey!

I just discovered linq2db and linq2db.EntityFramwrokCore while searching for a Bulk Insert option that would work with EF Core 3.1 and Oracle.
At first I was a bit skeptical of it being so simple to work with. Now I think I may be missing something, because it's not working for me.

Ok, so I have a collection of entity that I need to upsert into my Oracle (19c) database. This is the code:

LinqToDBForEFTools.Initialize();
List<FlatConsult> data = GetData();
dwDb.BulkCopy(new BulkCopyOptions 
{ 
    BulkCopyType = OracleTools.DefaultBulkCopyType, 
    TableName = "ST.\"FlatConsults\"" 
}, data);

I had to specify the table name otherwise I would get a โ€œORA-00942: table or view does not existโ€ error. But now I keep getting a "ORA-00928: missing SELECT keyword" error:

Oracle.ManagedDataAccess.Client.OracleException (0x80004005): ORA-00928: palavra-chave SELECT nรฃo encontrada
   em OracleInternal.ServiceObjects.OracleConnectionImpl.VerifyExecution(Int32& cursorId, Boolean bThrowArrayBindRelatedErrors, SqlStatementType sqlStatementType, Int32 arrayBindCount, OracleException& exceptionForArrayBindDML, Boolean& hasMoreRowsInDB, Boolean bFirstIterationDone)
   em OracleInternal.ServiceObjects.OracleCommandImpl.ExecuteNonQuery(String commandText, OracleParameterCollection paramColl, CommandType commandType, OracleConnectionImpl connectionImpl, Int32 longFetchSize, Int64 clientInitialLOBFS, OracleDependencyImpl orclDependencyImpl, Int64[]& scnFromExecution, OracleParameterCollection& bindByPositionParamColl, Boolean& bBindParamPresent, OracleException& exceptionForArrayBindDML, OracleConnection connection, OracleLogicalTransaction& oracleLogicalTransaction, Boolean isFromEF)
   em Oracle.ManagedDataAccess.Client.OracleCommand.ExecuteNonQuery()
   em LinqToDB.Data.DataConnection.ExecuteNonQuery(IDbCommand command) na D:\a\1\s\Source\LinqToDB\Data\DataConnection.cs:linha 1256
   em LinqToDB.Data.DataConnection.ExecuteNonQuery() na D:\a\1\s\Source\LinqToDB\Data\DataConnection.cs:linha 1261
   em LinqToDB.Data.CommandInfo.Execute() na D:\a\1\s\Source\LinqToDB\Data\CommandInfo.cs:linha 863
   em LinqToDB.DataProvider.MultipleRowsHelper.Execute() na D:\a\1\s\Source\LinqToDB\DataProvider\MultipleRowsHelper.cs:linha 100
   em LinqToDB.DataProvider.BasicBulkCopy.MultipleRowsCopyHelper(MultipleRowsHelper helper, IEnumerable source, String from, Action`1 prepFunction, Action`3 addFunction, Action`1 finishFunction, Int32 maxParameters, Int32 maxSqlLength) na D:\a\1\s\Source\LinqToDB\DataProvider\BasicBulkCopy.cs:linha 279
   em LinqToDB.DataProvider.Oracle.OracleBulkCopy.OracleMultipleRowsCopy1(MultipleRowsHelper helper, IEnumerable source) na D:\a\1\s\Source\LinqToDB\DataProvider\Oracle\OracleBulkCopy.cs:linha 186
   em LinqToDB.DataProvider.Oracle.OracleBulkCopy.MultipleRowsCopy[T](ITable`1 table, BulkCopyOptions options, IEnumerable`1 source) na D:\a\1\s\Source\LinqToDB\DataProvider\Oracle\OracleBulkCopy.cs:linha 126
   em LinqToDB.DataProvider.BasicBulkCopy.BulkCopy[T](BulkCopyType bulkCopyType, ITable`1 table, BulkCopyOptions options, IEnumerable`1 source) na D:\a\1\s\Source\LinqToDB\DataProvider\BasicBulkCopy.cs:linha 21
   em LinqToDB.DataProvider.Oracle.OracleDataProvider.BulkCopy[T](ITable`1 table, BulkCopyOptions options, IEnumerable`1 source) na D:\a\1\s\Source\LinqToDB\DataProvider\Oracle\OracleDataProvider.cs:linha 300
   em LinqToDB.Data.DataConnectionExtensions.BulkCopy[T](DataConnection dataConnection, BulkCopyOptions options, IEnumerable`1 source) na D:\a\1\s\Source\LinqToDB\Data\DataConnectionExtensions.cs:linha 2194
   em LinqToDB.EntityFrameworkCore.LinqToDBForEFTools.BulkCopy[T](DbContext context, BulkCopyOptions options, IEnumerable`1 source) na D:\a\1\s\Source\LinqToDB.EntityFrameworkCore\LinqToDBForEFTools.ContextExtensions.cs:linha 32
   em Mantic.BlackOps.Jobs.Maintenance.Utils.FlatConsultsProcessor.<UpdateConsultsAsync>d__5.MoveNext() na C:\Repos\Tekap.Mantic.BlackOps\Mantic.BlackOps.Jobs.Maintenance\Utils\FlatConsultsProcessor.cs:linha 116
--- Fim do rastreamento de pilha do local anterior onde a exceรงรฃo foi gerada ---
   em System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   em System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   em System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   em Mantic.BlackOps.Jobs.Maintenance.Jobs.FlatConsultsJob.<OrchestrateAsync>d__6.MoveNext() na C:\Repos\Tekap.Mantic.BlackOps\Mantic.BlackOps.Jobs.Maintenance\Jobs\FlatConsultsJob.cs:linha 79
[12:28:02 WRN T09] Failed to process the job '1': an exception occurred. Retry attempt 1 of 3 will be performed in 00:00:33. (Hangfire.AutomaticRetryAttribute)
Oracle.ManagedDataAccess.Client.OracleException (0x80004005): ORA-00928: palavra-chave SELECT nรฃo encontrada
   em OracleInternal.ServiceObjects.OracleConnectionImpl.VerifyExecution(Int32& cursorId, Boolean bThrowArrayBindRelatedErrors, SqlStatementType sqlStatementType, Int32 arrayBindCount, OracleException& exceptionForArrayBindDML, Boolean& hasMoreRowsInDB, Boolean bFirstIterationDone)
   em OracleInternal.ServiceObjects.OracleCommandImpl.ExecuteNonQuery(String commandText, OracleParameterCollection paramColl, CommandType commandType, OracleConnectionImpl connectionImpl, Int32 longFetchSize, Int64 clientInitialLOBFS, OracleDependencyImpl orclDependencyImpl, Int64[]& scnFromExecution, OracleParameterCollection& bindByPositionParamColl, Boolean& bBindParamPresent, OracleException& exceptionForArrayBindDML, OracleConnection connection, OracleLogicalTransaction& oracleLogicalTransaction, Boolean isFromEF)
   em Oracle.ManagedDataAccess.Client.OracleCommand.ExecuteNonQuery()
   em LinqToDB.Data.DataConnection.ExecuteNonQuery(IDbCommand command) na D:\a\1\s\Source\LinqToDB\Data\DataConnection.cs:linha 1256
   em LinqToDB.Data.DataConnection.ExecuteNonQuery() na D:\a\1\s\Source\LinqToDB\Data\DataConnection.cs:linha 1261
   em LinqToDB.Data.CommandInfo.Execute() na D:\a\1\s\Source\LinqToDB\Data\CommandInfo.cs:linha 863
   em LinqToDB.DataProvider.MultipleRowsHelper.Execute() na D:\a\1\s\Source\LinqToDB\DataProvider\MultipleRowsHelper.cs:linha 100
   em LinqToDB.DataProvider.BasicBulkCopy.MultipleRowsCopyHelper(MultipleRowsHelper helper, IEnumerable source, String from, Action`1 prepFunction, Action`3 addFunction, Action`1 finishFunction, Int32 maxParameters, Int32 maxSqlLength) na D:\a\1\s\Source\LinqToDB\DataProvider\BasicBulkCopy.cs:linha 279
   em LinqToDB.DataProvider.Oracle.OracleBulkCopy.OracleMultipleRowsCopy1(MultipleRowsHelper helper, IEnumerable source) na D:\a\1\s\Source\LinqToDB\DataProvider\Oracle\OracleBulkCopy.cs:linha 186
   em LinqToDB.DataProvider.Oracle.OracleBulkCopy.MultipleRowsCopy[T](ITable`1 table, BulkCopyOptions options, IEnumerable`1 source) na D:\a\1\s\Source\LinqToDB\DataProvider\Oracle\OracleBulkCopy.cs:linha 126
   em LinqToDB.DataProvider.BasicBulkCopy.BulkCopy[T](BulkCopyType bulkCopyType, ITable`1 table, BulkCopyOptions options, IEnumerable`1 source) na D:\a\1\s\Source\LinqToDB\DataProvider\BasicBulkCopy.cs:linha 21
   em LinqToDB.DataProvider.Oracle.OracleDataProvider.BulkCopy[T](ITable`1 table, BulkCopyOptions options, IEnumerable`1 source) na D:\a\1\s\Source\LinqToDB\DataProvider\Oracle\OracleDataProvider.cs:linha 300
   em LinqToDB.Data.DataConnectionExtensions.BulkCopy[T](DataConnection dataConnection, BulkCopyOptions options, IEnumerable`1 source) na D:\a\1\s\Source\LinqToDB\Data\DataConnectionExtensions.cs:linha 2194
   em LinqToDB.EntityFrameworkCore.LinqToDBForEFTools.BulkCopy[T](DbContext context, BulkCopyOptions options, IEnumerable`1 source) na D:\a\1\s\Source\LinqToDB.EntityFrameworkCore\LinqToDBForEFTools.ContextExtensions.cs:linha 32
   em Mantic.BlackOps.Jobs.Maintenance.Utils.FlatConsultsProcessor.<UpdateConsultsAsync>d__5.MoveNext() na C:\Repos\Tekap.Mantic.BlackOps\Mantic.BlackOps.Jobs.Maintenance\Utils\FlatConsultsProcessor.cs:linha 116
--- Fim do rastreamento de pilha do local anterior onde a exceรงรฃo foi gerada ---
   em System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   em System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   em System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   em Mantic.BlackOps.Jobs.Maintenance.Jobs.FlatConsultsJob.<OrchestrateAsync>d__6.MoveNext() na C:\Repos\Tekap.Mantic.BlackOps\Mantic.BlackOps.Jobs.Maintenance\Jobs\FlatConsultsJob.cs:linha 88
--- Fim do rastreamento de pilha do local anterior onde a exceรงรฃo foi gerada ---
   em System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   em System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   em System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   em Mantic.BlackOps.Jobs.Maintenance.Jobs.FlatConsultsJob.<>c__DisplayClass5_0.<<Start>b__0>d.MoveNext() na C:\Repos\Tekap.Mantic.BlackOps\Mantic.BlackOps.Jobs.Maintenance\Jobs\FlatConsultsJob.cs:linha 41
--- Fim do rastreamento de pilha do local anterior onde a exceรงรฃo foi gerada ---
   em System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   em System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   em System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   em Mantic.BlackOps.Jobs.Maintenance.Jobs.FlatConsultsJob.<Start>d__5.MoveNext() na C:\Repos\Tekap.Mantic.BlackOps\Mantic.BlackOps.Jobs.Maintenance\Jobs\FlatConsultsJob.cs:linha 40

I even added linq2db.Oracle.Managed to see if it would help, but no success. I'm probably missing some more configuration, but I couldn't find any help on it.

And thank you for your work!

Regression in L2DB 3.0.0-rc0 + linq2db.EntityFrameworkCore 3.2.0 - Null reference exception

I'm facing regression on following code path, I receive crashes with null reference exception. The code worked fine with L2DB 2.xx + EF Core provider 2.xx

I'm attaching a sample repro for the problem
CrashRep.zip

Sample code goes like this:

var query = db.ACL_ItemTicketDate.ToLinqToDB()
                                 .Where(p => p.Id < 1000)
                                 .GroupBy(p => p.ACL_Item)
                                 .Select(p => new 
                                 {
                                     AclItemId = p.Key.Id,
                                     AclItemName = p.Key.Name,
                                     TotalEntryCount = p.Key.ACL_Entries.Sum(ec => ec.EntriesCount),
                                     TotalEntryAllowed = p.Key.ACL_ItemTicketDates.Select(at => new 
                                     {
                                         EntryCount = at.EntryCount
                                     }).ToList()
                                 });

And the crash stack trace like this:

at LinqToDB.EntityFrameworkCore.EFCoreMetadataReader.CompareProperty(MemberInfo property, MemberInfo memberInfo)
at LinqToDB.EntityFrameworkCore.EFCoreMetadataReader.CompareProperty(IProperty property, MemberInfo memberInfo)
at LinqToDB.EntityFrameworkCore.EFCoreMetadataReader.<>c__DisplayClass8_0`1.<GetAttributes>b__1(IProperty p)
at System.Linq.Enumerable.TryGetFirst[TSource](IEnumerable`1 source, Func`2 predicate, Boolean& found)
at LinqToDB.EntityFrameworkCore.EFCoreMetadataReader.GetAttributes[T](Type type, MemberInfo memberInfo, Boolean inherit)
at LinqToDB.Mapping.MappingSchema.<>c__DisplayClass51_0`1.<GetAttributes>b__0(IMetadataReader mr)
at System.Linq.Enumerable.<SelectManyIterator>d__180`3.MoveNext()
at System.Collections.Generic.LargeArrayBuilder`1.AddRange(IEnumerable`1 items)
at System.Collections.Generic.EnumerableHelpers.ToArray[T](IEnumerable`1 source)
at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
at LinqToDB.Mapping.MappingSchema.GetAttributes[T](Type type, MemberInfo memberInfo, Boolean inherit)
at LinqToDB.Mapping.MappingSchema.GetAttributes[T](Type type, MemberInfo memberInfo, Func`2 configGetter, Boolean inherit, Boolean exactForConfiguration)
at LinqToDB.Mapping.EntityDescriptor.Init()
at LinqToDB.Mapping.EntityDescriptor..ctor(MappingSchema mappingSchema, Type type)
at LinqToDB.Mapping.MappingSchema.<>c__DisplayClass91_0.<GetEntityDescriptor>b__0(ICacheEntry o)
at LinqToDB.Common.Internal.Cache.CacheExtensions.GetOrCreate[TItem](IMemoryCache cache, Object key, Func`2 factory)
at LinqToDB.Mapping.MappingSchema.GetEntityDescriptor(Type type)
at LinqToDB.SqlQuery.SqlTable..ctor(MappingSchema mappingSchema, Type objectType, String physicalName)
at LinqToDB.Linq.Builder.TableBuilder.TableContext..ctor(ExpressionBuilder builder, BuildInfo buildInfo, Type originalType)
at LinqToDB.Linq.Builder.TableBuilder.BuildSequence(ExpressionBuilder builder, BuildInfo buildInfo)
at LinqToDB.Linq.Builder.ExpressionBuilder.BuildSequence(BuildInfo buildInfo)
at LinqToDB.Linq.Builder.WhereBuilder.BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
at LinqToDB.Linq.Builder.MethodCallBuilder.BuildSequence(ExpressionBuilder builder, BuildInfo buildInfo)
at LinqToDB.Linq.Builder.ExpressionBuilder.BuildSequence(BuildInfo buildInfo)
at LinqToDB.Linq.Builder.GroupByBuilder.BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
at LinqToDB.Linq.Builder.MethodCallBuilder.BuildSequence(ExpressionBuilder builder, BuildInfo buildInfo)
at LinqToDB.Linq.Builder.ExpressionBuilder.BuildSequence(BuildInfo buildInfo)
at LinqToDB.Linq.Builder.SelectBuilder.BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
at LinqToDB.Linq.Builder.MethodCallBuilder.BuildSequence(ExpressionBuilder builder, BuildInfo buildInfo)
at LinqToDB.Linq.Builder.ExpressionBuilder.BuildSequence(BuildInfo buildInfo)
at LinqToDB.Linq.Builder.ExpressionBuilder.Build[T]()
at LinqToDB.Linq.Query`1.CreateQuery(IDataContext dataContext, Expression expr)
at LinqToDB.Linq.Query`1.GetQuery(IDataContext dataContext, Expression& expr)
at LinqToDB.Linq.ExpressionQuery`1.GetQuery(Expression& expression, Boolean cache)
at LinqToDB.Linq.ExpressionQuery`1.System.Collections.Generic.IEnumerable<T>.GetEnumerator()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at CrashRepro.Program.Main(String[] args) in C:\Users\Bruno\Desktop\CrashRep\CrashRepro\Program.cs:line 35

in code it's decimal,but in sqlserver it can be null ,how to solve

 var qry =
        from dQry in depositQry
        from qry1 in (from cQry in consumeQry
                        from oiQry in orderQry.FullJoin(m => m.GoodsBrandCode == cQry.GoodsBrandCode)
                        select new { cQry, oiQry })
            .FullJoin(m => m.oiQry.GoodsBrandCode == dQry.GoodsBrandCode)
        group new { qry1, dQry } by qry1.oiQry.GoodsBrandCode into g 
        select new GoodsBrandAnalysisOutput
        {
            SaleAmout = g.Sum(m => m.qry1.oiQry.SaleAmout  - m.qry1.cQry.ConsumeAmout + m.dQry.DepositAmount),
            GoodsBrandCode = g.Key,
            SaleQnty = g.Sum(m => m.qry1.oiQry.SaleQnty - m.qry1.cQry.ConsumeQty + m.dQry.DepositQty)
        };

m.qry1.cQry.ConsumeAmout may be is NULL in sqlserver
but m.qry1.cQry.ConsumeAmout in code is decimal not decimal?
how to set m.qry1.cQry.ConsumeAmout default is 0;

/*i want like this*/
ISNULL(m.qry1.cQry.ConsumeAmout,0)

SQLite - an update on column with DateTimeOffset? throws exception

An update on column with DateTimeOffset? throws exception:

Exception message:
Stack trace:
Message: 
    System.ArgumentException : Property 'Int64 Ticks' is not defined for type 'System.Nullable`1[System.DateTimeOffset]' (Parameter 'property')
  Stack Trace: 
    Expression.Property(Expression expression, PropertyInfo property)
    Expression.MakeMemberAccess(Expression expression, MemberInfo member)
    Extensions.TransformX(MemberExpression e, Func`2 func)
    Extensions.Transform(Expression expr, Func`2 func)
    Extensions.TransformX(BinaryExpression e, Func`2 func)
    Extensions.Transform(Expression expr, Func`2 func)
    Extensions.TransformX(BinaryExpression e, Func`2 func)
    Extensions.Transform(Expression expr, Func`2 func)
    Extensions.TransformX(BinaryExpression e, Func`2 func)
    Extensions.Transform(Expression expr, Func`2 func)
    Extensions.GetBody(LambdaExpression lambda, Expression exprToReplaceParameter)
    InternalExtensions.ApplyLambdaToExpression(LambdaExpression convertLambda, Expression expression)
    ColumnDescriptor.ApplyConversions(MappingSchema mappingSchema, Expression getterExpr, DbDataType dbDataType, IValueConverter valueConverter, Boolean includingEnum)
    ColumnDescriptor.ApplyConversions(Expression getterExpr, DbDataType dbDataType, Boolean includingEnum)
    ExpressionBuilder.PrepareConvertersAndCreateParameter(ValueTypeExpression newExpr, Expression valueExpression, String name, ColumnDescriptor columnDescriptor, BuildParameterType buildParameterType)
    ExpressionBuilder.BuildParameterFromArgument(MethodCallExpression methodCall, Int32 argumentIndex, ColumnDescriptor columnDescriptor, BuildParameterType buildParameterType)
    UpdateBuilder.ParseSet(ExpressionBuilder builder, LambdaExpression extract, MethodCallExpression updateMethod, Int32 valueIndex, IBuildContext select, List`1 items)
    Set.BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
    MethodCallBuilder.BuildSequence(ExpressionBuilder builder, BuildInfo buildInfo)
    ExpressionBuilder.BuildSequence(BuildInfo buildInfo)
    UpdateBuilder.BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
    MethodCallBuilder.BuildSequence(ExpressionBuilder builder, BuildInfo buildInfo)
    ExpressionBuilder.BuildSequence(BuildInfo buildInfo)
    ExpressionBuilder.Build[T]()
    Query`1.CreateQuery(IDataContext dataContext, Expression expr)
    Query`1.GetQuery(IDataContext dataContext, Expression& expr)
    ExpressionQuery`1.GetQuery(Expression& expression, Boolean cache)
    IQueryProvider.Execute[TResult](Expression expression)
    LinqExtensions.Update[T](IUpdatable`1 source)
            dbContext
                .Tables.ToLinqToDBTable()
                .Where(x => x.Id== id)
                .Set(x => x.Date, DateTime.UtcNow)
                .Update();

Environment details

linq2db.EntityFrameworkCore version: 3.6.6
Database Server: Windows
Database Provider: SQLite
Operating system: W10
.NET Framework: Core 3

[net5.0] Using OrderBy followed by ThenBy inside RowNumber results in swapped columns for sorting

Using both OrderByand ThenBy inside RowNumber in a Linq2Db query results in an erroneous raw SQL query where the columns used in OrderBy and ThenBy are swapped, i.e., ...Sql.Ext.RowNumber().Over().OrderBy(A).ThenBy(B)... results in the following erroneous query string like ...ROW_NUMBER() OVER(ORDER BY B, A)....

Here's an MWE with two test cases demonstrating the issue: Linq2DbMWE.zip

It was working before updating to net5.0.

Custom converter does not work when entity type inherits from base class

There seems to be a problem with custom converters [or at least it seems to me so as the issue happens only for custom-mapped classes] when entity type inherits from a base class.

I'm attaching a repro project here
JsonRepro2.zip

The sample program goes like this

Program:

using JsonRepro.BaseEntities;
using LinqToDB.Data;
using LinqToDB.EntityFrameworkCore;
using Newtonsoft.Json;
using System;
using System.Linq;

namespace JsonRepro
{
    class Program
    {
        static void Main(string[] args)
        {
            var db = new StrippedDownContext();
            LinqToDBForEFTools.Initialize();

            // converting from string, because usually JSON is stored as string, but it depends on DataProvider
            LinqToDB.Mapping.MappingSchema.Default.SetConverter<string, LocalizedString>(v => JsonConvert.DeserializeObject<LocalizedString>(v));

            // here we told linq2db how to pass converted value as DataParameter.
            LinqToDB.Mapping.MappingSchema.Default.SetConverter<LocalizedString, DataParameter>(v => new DataParameter("", JsonConvert.SerializeObject(v), LinqToDB.DataType.NVarChar));

            //L2D crash
            var l2dCrash = db.EventScheduleItems.Where(p => p.Id < 10).Select(p => new
            {
                p.Id,
                p.NameLocalized
            }).ToLinqToDB().FirstOrDefault();
        }
    }
}

Stripped down context:

using JsonRepro.BaseEntities;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json;

namespace JsonRepro.BaseEntities
{
    public class LocalizedString
    {
        public string English { get; set; }
        public string German { get; set; }
        public string Slovak { get; set; }
    }

    public class EventScheduleItemBase 
    {
        public EventScheduleItemBase()
        {
        }

        public int Id { get; set; }
        public virtual LocalizedString NameLocalized {  get; set; }
    }

}

    namespace JsonRepro
{
    public class EventScheduleItem : EventScheduleItemBase
    {
        public EventScheduleItem()
        {
        }
    }

    public class StrippedDownContext : DbContext
    {
        public StrippedDownContext()
        {
        }

        public StrippedDownContext(DbContextOptions<StrippedDownContext> options)
            : base(options)
        {
        }


        public virtual DbSet<EventScheduleItem> EventScheduleItems { get; set; }


        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            if (!optionsBuilder.IsConfigured)
            {
                optionsBuilder.UseSqlServer("conn string");
            }
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<EventScheduleItem>(entity =>
            {
                entity.ToTable("EventScheduleItem");
                entity.Property(e => e.NameLocalized)
                      .HasColumnName("NameLocalized_JSON")
                      .HasConversion(v => JsonConvert.SerializeObject(v), v => JsonConvert.DeserializeObject<LocalizedString>(v));


            });
        }
    }
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.