SQL inside C# strings, fragment editor, run query in console – Language injection updates in Rider 2018.3

Maarten Balliauw

The latest Rider 2018.3 EAP build extends Rider’s language injections functionality quite a bit, with SQL language support in string literals. This gives us highlighting, code completion and code analysis, and a Run in console action for SQL inside of a C# string!

For all existing and newly added language injections, we can edit fragments in a separate editor! And last but not least, we can now configure automatic language injections, so that Rider automatically recognizes language fragments inside strings.

More than enough for a long blog post! Grab a coffee or tea, sit back, and let’s dive in!

What are language injections again?

Sometimes we have to embed a piece of code in a string literal. For example, pieces of HTML inside a JavaScript string, or a quick JSON fragment inside a C# string. Rider supports marking a string literal as containing another programming language, so that we get highlighting, code completion, code analysis and more inside of a string!

Inject JSON into string literal

That’s the main premise. In case you want to read more about language injections in Rider before, go read up on them. Now let’s look at what’s new in Rider 2018.3!

SQL language injections – make working with Entity Framework and Dapper more enjoyable

For those developers using Entity Framework’s SqlQuery to work with raw SQL queries, or those using a data access framework like Dapper which is string-based, we have great news!

After setting up a database connection in Rider, we can mark any string as being a SQL fragment, and get highlighting, code completion and code analysis based on the schema of the database we are connected to!

Code completion inside a string for a connected SQL database

That’s right: code completion based on our connected SQL database, inside a C# string literal!

Note that this also works with Data Definition Language (DDL) database connections: if you have a folder containing .sql files that define tables, views, …, Rider will provide code completion for those as well.

Data definition language database code completion

Having support for injected SQL fragments should help us in writing raw SQL queries in our code, which is especially useful when using the various micro-ORM’s (such as Dapper) out there.

The Run query in console context action

For strings that contain injected SQL, Rider provides highlighting, code completion and code analysis. Not only that: database-related context actions (Alt+Enter) become available as well, such as running a query from C# string in the database console:

Run query from C# editor in database console

No more need to open up a database console and copy/paste a query in there!

Tip: check our blog series to learn more about working with databases in Rider.

Edit language injection fragments in a separate editor

Previously, when working with language injections, we would have to manually escape special characters that were not allowed inside the “host” language. For example when injecting JSON into a string, we’d still have to escape " to \".

Rider 2018.3 adds the ability to edit an injected language fragment in a separate editor, and ensures that the contents we are editing are properly escaped in the original document:

Edit language fragment in separate editor

This works for SQL as well, including context actions (Alt+Enter):

Edit SQL statement in fragment editor

Automatic language injections

Marking a string as an injected language only applies to our local Rider instance. To share language injections with team members, we can add a // language={language-name} comment on the line before the string literal. However, that does require some discipline.

Rider 2018.3 comes with automatic language injections based on patterns, so that strings similar to SELECT ... FROM ... are recognized as a SQL language injection while typing:

Automatic recognizition of SQL

We can add our own patterns in Rider’s settings, under Editor | Language Injections:

Edit automatic language injection patterns

Have a look at the existing ones for inspiration.

Additional injected languages

So far, we have covered support for SQL language injections. For Rider 2018.3, we have been hard at work to support injecting additional languages.

By merging language injection functionality from IntelliJ IDEA and ReSharper, we now support languages like CSS, HTML, JSON, regular expressions and JavaScript, as well as SQL, XML, MsBuild, YAML, and many more.

Current limitations/external annotations

When using certain types and methods, Rider knows that certain parameters accept string value containing a certain language. For example, when typing Regex.Matches(value, "{caret here}"), the editor knows the second string parameter accepts a regular expression and provides highlighting and code completion for it.

This works because we maintain a large collection of external annotations, where we keep information about the .NET base class library (BCL) and various open-source projects. The Regex.Matches example can be seen here.

Tip: check our blog series about how code annotations can help make Rider smarter on your code base!

Currently, Rider (and ReSharper) do not have external annotations that would, for example, annotate methods in Entity Framework and Dapper. The automatic language injection patterns described earlier should help for these cases.

Download Rider 2018.3 EAP and give it a try! We would love to hear your feedback on these updates!

Comments below can no longer be edited.

25 Responses to SQL inside C# strings, fragment editor, run query in console – Language injection updates in Rider 2018.3

  1. Ris says:

    October 29, 2018

    Will this also be available as a language injection in resharper?

    • Maarten Balliauw says:

      October 29, 2018

      Right now, this is not on the short-term roadmap. However, feel free to open a request for this at https://youtrack.jetbrains.com/issues/RSRP

      • Thomas Due says:

        October 29, 2018

        There is already such a request, and there has been for a year:
        https://youtrack.jetbrains.com/issue/RSRP-465065

        Fairly disappointed that this is a Rider only feature.

        • Maarten Balliauw says:

          October 30, 2018

          Sorry to hear that, best is to stay subscribed to that issue, so you will hear when work is being done on it.

        • Eamon Nerbonne says:

          October 30, 2018

          Yeah it’s disappointing :-/.

          I also now notice that this is a youtrack issue with 8 follows; but I’d also independently suggested that in one of those pop-up suggestions that appear after a few weeks of usage, and that doesn’t appear to have turned into an issue, so I’m kind of assuming there are more than 8 users that would be interested in this feature….

  2. Dwight says:

    October 29, 2018

    Right on! Screw ORMs, amirite?

    • Maarten Balliauw says:

      October 30, 2018

      Well… no? 🙂 We’re using Entity Framework, with its SqlQuery() support. While the query thet is raw SQL, all other elements of the framework are still being used to create Objects from the Relational database and Map them. A similar framework would be Dapper, which is a bit more lightweight and only supports reading and not mutations. The idea of these is that you can tune your SQL query instead of relying on the framework to get it right, but still keep other benefits of the ORM.

      Good and recommended reads in case you want to check:

      * https://docs.microsoft.com/en-us/ef/ef6/querying/raw-sql
      * https://github.com/StackExchange/Dapper

      • Eamon Nerbonne says:

        October 30, 2018

        I think you’re using the term ORM in different fashions. Strictly speaking dapper might be considered an ORM (although it doesn’t really do any relational mapping, it does unpack tuples into objects), but to others the word ORM means something larger such as EF or NHibernate.

        • Maarten Balliauw says:

          October 30, 2018

          Well, yeah, agree. But bottom line: those who like crafting raw SQL will definitely benefit from this one, and those who like e.g. EF’s LINQ approach benefit from regular code completion in Rider 🙂

  3. PasserBy says:

    October 30, 2018

    Is Rider development funded from ReSharper money? It’s kind of lame to see ReSharper being neglected.

    • Maarten Balliauw says:

      October 30, 2018

      We are working on a lot of architectural changes for ReSharper, and those are unfortunately a bit less visible right now. They do open a bright path to the future.

      Both projects are actively developed and there’s a lot of new features to be implemented still in both ReSharper and Rider.

      Happy to hear your feedback about both products!

  4. Davi says:

    October 30, 2018

    Have you got an example of using the // language={language}? I can’t seem to get it working in 2018.3 EAP 4

  5. Paul Reid says:

    October 30, 2018

    Awesome, I’ve been waiting for this IntelliJ feature for a while!

    Also for all those that feel like R# is being neglected, it’s not! The Rider team is just taking advantage of what’s already in the IntelliJ platform and making it compatible with the R# process they use to make Rider, they’re not writing brand new Rider exclusive features here. You can’t possibly expect the guys to backport the entire IntelliJ platform to R#!

  6. Dan says:

    November 1, 2018

    I finally had a chance to download and install this EAP release
    I’m able to write SQL in a C# string and use the “Run query in console” feature to see the results, but the Code Completion is not working.

    Can anybody help?
    Thanks!

    • Maarten Balliauw says:

      November 2, 2018

      Can you check whether the string is on one line, and without any interpolations?

      If that’s the case and it still does not show completion, would you mind opening an issue at https://youtrack.jetbrains.com/issues/RIDER ?

      • Dan says:

        November 2, 2018

        I tried both multi-line and single linen SQL, neither with string interpolation. I’ll open a ticket.

        Thanks for the reply, Maarten!

  7. JetBrainsのクロスプラットフォーム対応.NET IDE「Rider」誕生までの歴史とそのアーキテクチャ | JetBrains ブログ says:

    November 8, 2018

    […] JetBrainsは、単に既存のプラグインと機能を組み合わせるだけでなく、1+1=3になるように機能を拡張しようと積極的に考えています。例えば、 C#ファイルの文字列の中にSQLコード補完を提供することができれば、どれくらいうれしいですか?または、そのクエリを実行するAlt + Enterアクションを提供しますか?これはまさに私たちが取り組んでいることです(Rider 2018.3でSQLに対するLanguage Injection機能が拡充されます)。両方のプロセス(さらに、おそらく、他に協調するマイクロサービス)からインテリジェンスが得られるため、IDEはさらにスマートになります。 […]

  8. Steve W says:

    February 24, 2019

    This is great, is there a way to make this work with F# too? I had a look at the Editor > Language Injections settings but didn’t have any luck 🙂

  9. Andreas Gullberg Larsen says:

    November 14, 2019

    I get ‘unable to resolve variable’ when using SqlParameter to safely inject values.
    I want the schema intellisense, but I need it to shut up about these variables it is expecting to see. Any ideas?

    • Jeremy Seekamp says:

      February 20, 2020

      Did you ever find a resolution to this issue? I’m having the same issue.

Subscribe

Subscribe to .NET Tools updates