Thursday, January 30, 2020

The project was restored using Microsoft.NETCore.App version X, but with current settings, version Y would be used instead

When I came across this error in devops build pipelines, I initially though that there must have been some uninted change done by visual studio to project file which causes this error. However after checking diff it was clear that there were absolutely no changes in the two commits apart from whitespaces.

Thus reason for this error became a suspense until I stumbled across this post

https://gert-cominotto.be/2019/02/18/azure-devops-functions-build-fails-the-project-was-restored-using-microsoft-netcore-app-version-1-0-0-but-with-current-settings-version-2-1-6-would-be-used-instead/

It basically says that the error is caused by Nuget Restore task in Azure pipeline which always uses dot net core 1.0.0.

And the solution is to use dotnet restore task instead of Nuget restore task.


Friday, January 24, 2020

Azure devops Invoke-Sqlcmd login failed

In one of the projects using Azure devops deployment pipelines the deployment worked on Staging, but failed on production server. Logs indicated that a command using Invoke-Sqlcmd failed to authenticate the user. Error returned was of the form



Login failed for user '<User Id>'

The problem here is related to special characters in the password. So if Invoke-Sqlcmd command has special characters in a password and the password is enclosed with double quotes, it does not treat the password as literal string and instead tries to interpret it in different way. Thus the authentication fails.

Unfortunately since VSTS does not allow password to be passed using single quotes, the only option we have is to change the user's password.

More information about this error can be found at:

https://mohitgoyal.co/2017/08/09/vsts-azure-sql-database-deployment-task-keeps-failing-with-error-login-failed-for-user/

and also at

https://stackoverflow.com/questions/22335651/powershell-invoke-sqlcmd-login-failed

Many thanks to them.

Wednesday, January 22, 2020

Use multiple data access technologies in the same application

EF Core is a great tool to quickly build and test applications using database backends, however it does some issues related to performance. Particularly the queries were very very slow in one of the applications which has the SQL server database hosted in Azure SQL Database.

Thus finally we resorted to using two different data access technologies in the same application:

1) Dapper was used to query the database in read-only mode
2) EF Core was used for most (but not all) DML operations

This approach ensured that the data access layer has required flexibility without sacrificing speed of development.


A very good guide to using different data access technologies in the same application can be found at https://www.c-sharpcorner.com/article/combine-ado-net-ef-core-and-dapper-in-same-blazor-app/

Tuesday, January 21, 2020

Get SQL from EF core objects

There is an excellent method explained at http://rion.io/2016/10/19/accessing-entity-framework-core-queries-behind-the-scenes-in-asp-net-core/ for getting SQL queries out of EF Core objects. But this code works for EF Core 1, for EF core 2.1, the modified code is available at https://gist.github.com/nour-s/3bbf9b2588faa6b849393639a8b39757.

So we just need to add this class to our project:


public class IQueryableExtensions  
{
    private static readonly TypeInfo QueryCompilerTypeInfo = typeof(QueryCompiler).GetTypeInfo();

    private static readonly FieldInfo QueryCompilerField = typeof(EntityQueryProvider).GetTypeInfo().DeclaredFields.First(x => x.Name == "_queryCompiler");

    private static readonly PropertyInfo NodeTypeProviderField = QueryCompilerTypeInfo.DeclaredProperties.Single(x => x.Name == "NodeTypeProvider");

    private static readonly MethodInfo CreateQueryParserMethod = QueryCompilerTypeInfo.DeclaredMethods.First(x => x.Name == "CreateQueryParser");

    private static readonly FieldInfo DataBaseField = QueryCompilerTypeInfo.DeclaredFields.Single(x => x.Name == "_database");

    private static readonly FieldInfo QueryCompilationContextFactoryField = typeof(Database).GetTypeInfo().DeclaredFields.Single(x => x.Name == "_queryCompilationContextFactory");

    public static string ToSql<TEntity>(this IQueryable<TEntity> query) where TEntity : class
    {
        if (!(query is EntityQueryable<TEntity>) && !(query is InternalDbSet<TEntity>))
        {
            throw new ArgumentException("Invalid query");
        }

        var queryCompiler = (IQueryCompiler)QueryCompilerField.GetValue(query.Provider);
        var nodeTypeProvider = (INodeTypeProvider)NodeTypeProviderField.GetValue(queryCompiler);
        var parser = (IQueryParser)CreateQueryParserMethod.Invoke(queryCompiler, new object[] { nodeTypeProvider });
        var queryModel = parser.GetParsedQuery(query.Expression);
        var database = DataBaseField.GetValue(queryCompiler);
        var queryCompilationContextFactory = (IQueryCompilationContextFactory)QueryCompilationContextFactoryField.GetValue(database);
        var queryCompilationContext = queryCompilationContextFactory.Create(false);
        var modelVisitor = (RelationalQueryModelVisitor)queryCompilationContext.CreateQueryModelVisitor();
        modelVisitor.CreateQueryExecutor<TEntity>(queryModel);
        var sql = modelVisitor.Queries.First().ToString();

        return sql;
    }
}


And then simply call ToSQL() method like so:

var sql = query.ToSql(); 

Amazing isn't it?

`sass-loader` requires `node-sass` >=4


I was getting an error

Module build failed: Error: `sass-loader` requires `node-sass` >=4. Please install a compatible version.


The solution which works is:

  • Remove the node-sass from global npm-cache (For Windows users %userprofile%\AppData\Roaming\npm-cache)
  • Remove node-sass from your project's node_modules dir
  • Do npm install to reinstall node-sass

c# httpclient The remote certificate is invalid according to the validation procedure: RemoteCertificateNameMismatch

 If we get this error while trying to get http reponse using HttpClient object, it could mean that certificate validation fails for the remo...