-
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
Translate string.Join and string.Concat #2981
Comments
string.Join
support and extending LINQ to query
We have extensibility, we don't have any docs yet but you want to look at Leaving this open to track String.Join. We would definitely be interested in accepting a contribution for this. |
Notes: For SQL Server, you must use
(see this thread) |
Also: I'm planning to do a contribution when I get time. I'm waiting for the standard dust to settle after 1.0.0 before I use EF Core in production because I see a fair number of bugs. |
I understand this can be extended adding a new |
Look at |
I understand that, but isn't there a way to extend the functionality without using Internal namespaces? That isn't really "extensible" from my point of view. I don't wanna produce code that may break with every EF update if I'm just "extending" the framework. |
This issue talks about implementing functionality in EF core itself, which is not exactly "extending" framework. Rather extending (or improving to be more precise) Linq-to-SQL translation. Is there a specific reason you want to "extend" the framework? |
I was under the impression that EF supported extensibility from Rowan's comment. The ability to crate my own translators for common queries looks like a great feature. Similar to what nein-linq does. |
Let me revive this thread @rowanmiller : My first question is, if there is a general mistake in my thought? Imho calling CONCAT/CONCAT_WS would lead to a quite similar behavior as The second question refers to a gerneral strategy regarding the support of DBMS versions. As already mentioned there are two T-SQL functions to handle string concatenation - CONCAT and CONCAT_WS. While CONCAT is already available since SQLServer 2012 CONCAT_WS will be introduced with 2017. |
I'm pretty sure concat only works when the number of strings is known when building the query. Each string has to be passed in as an argument. It's not like you could do Last time I researched this, this was the state of the art, and it does require attention to avoid some tricky encoding corner cases: http://sqlblog.com/blogs/rob_farley/archive/2010/04/15/handling-special-characters-with-for-xml-path.aspx |
I still don't understand how we can add an Still no documentation on this? |
FWIW starting with SQL Server 2017, |
@jnm2 You're absolutely right, I confused relations with scalar values. SQL-Server won't execute a script like SELECT CONCAT(SELECT 'a' UNION SELECT 'b') Maybe I can find the time to work into the FOR XML PATH - thing and adopt my implementation accordingly. @divega: STRING_AGG seems to do the trick CONCAT isn't able to. But it will only work for SQLServer Versions >= 2017 and since there is just one general EFCore-package for SQLServer one would break the compatibility with the majority of SQLServer instances. |
Until now it just happens that we haven't added enough features that are version specific for it to become really compelling but we could certainly add API to enable groups of features for a version of the database server, e.g. the most granular version: optionsBuilder.UseSqlServer(connectionString, opt=>opt.Use2017Functions()); A bit more general: optionsBuilder.UseSqlServer(connectionString, opt=>opt.Use2017Features()); or even shorter: optionsBuilder.UseSqlServer2017(connectionString); We have discussed this before, e.g. at #9000 (comment) and #3011 (comment). |
@divega I personally like this approach, but its concrete implementation goes far beyond the borders of a normal contribution since it would (at least) touch all SQLServer specific mappers/translators/younameit. |
@akamud - The thing you want to achieve is custom translation. Check #7368 which adds user defined scalar functions. Then you will have a local function which would do string.Join for you and provide a SQL translation for that (using This issue talks about adding translation in-built in EF. Adding another @peterwurzinger - For implementation, you can start with very basic approach taking a translation which would work on all SqlServer editions. Then it would be localized enough to particular In 2nd phase we need to flow information about SqlServer2017 functions to methodcall translators. There would be 2 approaches to that.
|
As much as I was happy to discover STRING_AGG(), I cannot help but feel that it would have been better had sql server added support for an array datatype instead. I suspect that would solve quite a few things. |
@9Rune5 isn't array types supported by memory optimized tables/types? You can create memory optimized type and pass it as parameter I believe. I didn't not checked but I think this is supported. |
Sure, but in this case we want to have a column in the result set contain a subtable.
When I do stuff like that, EF generates queries with some mighty impressive joins and I am left with the feeling that those queries could be further optimized had SQL Server been able to return a table column type. Instead I'm left with some funky behaviour if I'm foolish enough to employ some .Skip() and .Take(). For me, string.Join() support is a desperate measure to get halfway to properly supporting the type of EF query in my example. I have a problematic join like this in some code I wrote recently, and STRING_AGG() seemed to go a long way of resolving the performance issues I witnessed. In that particular case I was able to live with the compromise of not having the data returned in an orderly fashion. A somewhat messy-looking string would have sufficed. But many of my assumptions could turn out to be dead wrong and the only real solution is lazy-loading (or something completely different). After almost a decade of using EF, my team still suffer from "maybe hand-written sql can get us out of this performance jam"-ities and that is unfortunate. (the result isn't nice) |
Not just string.join...mssql supports returning xml and json strings("FOR JSON AUTO" and "FOR JSON PATH" ). |
Null semantics of STRING_AGGDROP TABLE IF EXISTS data;
CREATE TABLE data
(
id INT PRIMARY KEY IDENTITY,
name VARCHAR(MAX),
);
-- Simple sample
INSERT INTO data (name) VALUES ('foo'), ('bar');
SELECT STRING_AGG(name, ', ') FROM data; -- foo, bar
-- NULLs are ignored and the corresponding separator is not added
DELETE FROM data WHERE 1=1;
INSERT INTO data (name) VALUES ('foo'), (NULL), ('bar');
SELECT STRING_AGG(name, ', ') FROM data; -- foo, bar
-- NULLs only results in NULL
DELETE FROM data WHERE 1=1;
INSERT INTO data (name) VALUES (NULL);
SELECT STRING_AGG(name, ', ') FROM data; -- NULL
-- Empty table results in NULL
DELETE FROM data WHERE 1=1;
SELECT STRING_AGG(name, ', ') FROM data; -- NULL |
* string.Join * string.Concat Closes dotnet#2981
* string.Join (SQL Server and SQLite) * string.Concat (SQL Server and SQLite) * Standard deviation and variance (SQL Server) Closes dotnet#2981 Closes dotnet#28104
@ajcvickers as this has been added to the 7.0.0 milestone does that mean that it will be included in EF Core 7? |
@wertzui that means that it's in the plan for 7.0, but since it's still open, work hasn't been done yet, so there's always a chance it may get pulled out of the release. Specifically for this though, there's a PR out, so chances are it will be in. |
* string.Join (SQL Server and SQLite) * string.Concat (SQL Server and SQLite) * Standard deviation and variance (SQL Server) Closes dotnet#2981 Closes dotnet#28104
* string.Join (SQL Server and SQLite) * string.Concat (SQL Server and SQLite) * Standard deviation and variance (SQL Server) Closes dotnet#2981 Closes dotnet#28104
@roji Is this done? |
Not yet, #28110 still has to be merged (I think there's very little left). |
* string.Join (SQL Server and SQLite) * string.Concat (SQL Server and SQLite) * Standard deviation and variance (SQL Server) Closes dotnet#2981 Closes dotnet#28104
I'm using the The following code works without any issues: var result = await this.Addresses
.Select(address => string.Join(", ",
new List<string>() { address.Street1, address.City, address.Country }))
.Take(10)
.ToListAsync(); However, when I try to filter out empty strings from the list using var result = await this.Addresses
.Select(address => string.Join(", ",
new List<string>() { address.Street1, address.City, address.Country }.Where(s => s != "")))
.Take(10)
.ToListAsync(); (it throws I'd expect both queries to work. Could someone provide some insight into why the second query doesn't execute properly? Is there something I'm overlooking or is it potentially a bug or limitation of the EF Core's LINQ provider? |
@magicxor the composition of LINQ operators over primitive collections ( |
string.Join
would be a cool feature to have now and then. Some database engines support this with an aggregate function, others such as SQL Server need a little hand-holding. Pluses include terser code and less data over the wire when projecting, since the alternative to concatenating on the server would be returning a child string collection for each row and concatenating the collection after the query. (If I understand correctly, child collections are usually transferred by joining each row of the child collection to the original row set and duplicating a lot of data.)I expect that this would be low priority for you to add to EF, but I'm curious if anything is being done to allow extensions to the LINQ to query translation. We would be thrilled to implement
string.Join
support ourselves if it didn't require modifying EF and provider source code every release and recompiling.I wasn't able to find anything about extending LINQ to query translation so I apologize if I missed it, but I know you are dramatically refactoring for EF Core and I can imagine many cool scenarios would be possible if there was an extension point in LINQ querying.
Depends on:
The text was updated successfully, but these errors were encountered: