6

NOTE: This appears to be a problem with the compiler that's used with SSDT projects, it's apparently fixed in the 2017 RC. My problem is similar to one described here.

I've got some code which refuses to let me write it as an expression-bodied function member. In short, I want to do this:

void foo() => bar();

But the IDE throws a tantrum and demands I write it like this:

void foo() { bar(); }

I mean sure, it's two extra characters but I'm not sure why it's complaining, the errors don't make sense either. It gives me the following 3 errors:

  • CS0000: ; expected
  • CS0000: Method must have a return type.
  • CS0000: Identifier expected.

The full code looks like this.

public static void foo() => bar("some param"); // Errors on this line.
static void bar(string myParam) { //20 lines of code } 

I've tested this in the C# interactive window and everything compiles and runs correctly. I can't find any unprintable characters in the code.

This is using VS 2015 community with the target framework being 4.6.1

Full code:

using System.Data.SqlClient;
using Microsoft.SqlServer.Server;

public partial class Triggers
{

    private const string ConnectionString = "context connection = true";

    private const string ReadInsertedTable = @"
    SELECT ID,
           (
               SELECT *
               FROM inserted AS b
               WHERE a.ID = b.ID
               FOR XML RAW, ELEMENTS XSINIL
           )
    FROM inserted AS a
";
    [SqlTrigger(Name = "Person_Insert", Target = "Person", Event = "FOR INSERT")]
    public static void Person_Insert() => AuditInsert(TableName); //  All errors here.

    private const string TableName = "Person";

    private static void AuditInsert(string tableName)
    {

        using (var readConnection = new SqlConnection(ConnectionString))
        using (var writeConnection = new SqlConnection(ConnectionString))
        {
            using (var readCommand = new SqlCommand(ReadInsertedTable, readConnection))
            {
                readConnection.Open();
                using (var reader = readCommand.ExecuteReader())
                {
                    SqlContext.Pipe.Send((reader));
                }
            }
        }
    }
}

enter image description here

Update: Code compiles using the msbuild utility but still fails in Visual Studio.

Matt
  • 25,467
  • 18
  • 120
  • 187
Jake
  • 1,701
  • 3
  • 23
  • 44
  • I have copied your code to my vs and it compiled without errors – Maksim Simkin Feb 04 '17 at 08:09
  • Any idea where to even start looking to try and fix this? Because CS0000 doesn't even seem to be a normal code. I'll add an image from my IDE. – Jake Feb 04 '17 at 08:19
  • what version of VS are you using? note that expression bodied members is feature of **C#6** so it does not work on old IDEs – M.kazem Akhgary Feb 04 '17 at 08:35
  • VS2015 Community w/ Update 3. – Jake Feb 04 '17 at 08:41
  • It's important that you mention in which enviroment you're working. In a Visual Studio 2015/2017 you can add the new compiler features to the project via NUGET package manager -> Manage Packages for Solution. Open it and browse for `Microsoft.Net.Compilers`. Then add it to the project and click INSTALL. Do the same for `Microsoft.CodeDom.Providers.DotNetCompilerPlatform`. Close NUGET and rebuild your project. – Matt Nov 27 '17 at 15:00

2 Answers2

5

This will have something to do with Roslyn. Try to run this:

Non-roslyn: https://dotnetfiddle.net/LJm1Fj

Roslyn: https://dotnetfiddle.net/aMUsj0

I suspect there's something wrong either with your project file or your Visual Studio installation because VS2015 should use Roslyn-based compiler by default.

I'd try:

  • creating a new project with the code from the fiddle above
  • if it compiles then compare the differences in the *.csproj files, mainly the ToolsVersion <Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> and targets <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
  • you should also look in the Output->Build window in VS and check out the executable being launched, in my case: C:\Program Files (x86)\MSBuild\14.0\bin\csc.exe /noconfig /nowarn:1701,1702,2008 /nostdlib+ /platform:anycpu32bitpreferred /errorreport:prompt /warn:4 /define:DEBUG;TRACE /errorendlocation /preferreduilang:en-US /highentropyva+ /reference:"C:\Program Files (x86)\Reference ... Using shared compilation with compiler from directory: C:\Program Files (x86)\MSBuild\14.0\bin
  • if it doesn't compile, I'd suggest reinstalling .NET and VS
rocky
  • 7,506
  • 3
  • 33
  • 48
  • Looks like it's using an old compiler. The csc.exe I'm getting is under C:\Windows\Microsoft.NET\Framework\v4.0.30319\Csc.exe. Any idea how to change it? – Jake Feb 04 '17 at 09:42
  • 1
    Have you tried to create the vanilla project as I suggested? I think there will be some differences in the project file, presumably in the targets section. Or maybe there is a specific language version set in the project file (Project properties -> Build -> Advanced -> Language Version). – rocky Feb 04 '17 at 09:46
  • Yeah, I've just done that. It's to do with the project type. Apparently SQL Server Database Projects' (SSDT) don't use Roslyn. – Jake Feb 04 '17 at 09:49
  • Yep, that's the answer. Either try to merge it with the vanilla c# project template or just use a clean c# project. I don't know what's so specific about SSDT project but if you really need to use it, try extracting the aforementioned logic to a "pure c#" project. – rocky Feb 04 '17 at 09:55
  • I'll look into it later. I don't mind compiling and deploying this from the command line. :-) Thanks again. – Jake Feb 04 '17 at 09:59
  • ;) Glad to help – rocky Feb 04 '17 at 09:59
  • 1
    @Jake What do you see when you do as in rocky's first comment, that is __Project properties -> Build -> Advanced -> Language Version__? Does the dropdown have only versions up to C# 5.0 for your project type? – Jeppe Stig Nielsen Feb 04 '17 at 10:01
  • 1
    I don't have Advanced under Build with an SSDT project. – Jake Feb 04 '17 at 10:03
  • 1
    @Jake I can reproduce what you see! If I create a new project, and choose "SQL Server Database Project", it creates a `.sqlproj` file, not a `.csproj` file. If in that SSDT project I add a new item and choose "SQL CLR C#" "Class", and in the resulting C# file use any C# 6.0 feature (also tried with an auto-property with initializer, `int P { get; set; } = 42;`), __I get strange errors__ when I try to "Build Solution (F6)". – Jeppe Stig Nielsen Feb 04 '17 at 10:25
  • That's pretty much what I did except I did a SQL CLR C# Trigger instead of a class. – Jake Feb 04 '17 at 10:28
  • I've put a link to that question at the top of my question. Thanks though. – Jake Feb 04 '17 at 10:44
0

This answer turned out to be largely irrelevant.

As the asker figured out himself, with help from user rocky, the issue is that an SQL Server Database Project (.sqlproj) (unlike other projects of type .csproj) is not built with the new C# 6.0 compiler, at least not in Visual Studio 2015. The thread linked by the asker, Usage of wrong compiler during SQL Server Database Project building, has some details.


Old answer:

In your image, the constant declaration:

private const string TableName = "Person";

is missing. However, you have not removed the tableName parameter from the AuditInsert method.

Community
  • 1
  • 1
Jeppe Stig Nielsen
  • 60,409
  • 11
  • 110
  • 181
  • The code is fine, this appears to be a problem with the compiler used for SSDT projects. Apparently it's fixed in the 2017 RC, but I won't be installing that anytime soon. :-) – Jake Feb 04 '17 at 09:52
  • @Jake How can `AuditInsert(TableName)` be fine when there is no `TableName` defined anywhere? I am looking at your image. – Jeppe Stig Nielsen Feb 04 '17 at 09:54
  • The image was just to show that the errors appeared since Maksim said it compiled fine for him. We've already established it's a compiler issue, not a code one. I'm updating my main question accordingly with a link to a related question. – Jake Feb 04 '17 at 09:56