繁体   English   中英

实体框架核心-执行原始SQL-SQL / SQLite的相同代码

[英]Entity Framework Core - Execute raw sql - Same code for SQL/SQLite

在我的LogService中插入新的异常时,我目前使用两种不同的Connections类型(正常使用的SQLConnection和集成测试的SqliteConnection)。

因为我无权访问数据库上下文类,所以必须使用原始sql插入新实体,(我只有数据库连接字符串)。

在运行集成测试时,由于实体关系,我必须在内存数据库中使用SQLite(SQL在内存中不支持此功能)。

protected async Task InsertException(DateTime utcNow, LogLevel logLevel, EventId eventId, string state, Exception exception, CategoryAppSettings categoryAppSettings, string caller, string ipAddress, int? userId, int? organisationId, string requestId)
{
    string stackTrace = exception?.StackTrace;

    string query =
        "INSERT INTO [Exception] " +
        "(" +
            "[Created]" +
            ",[EventId]" +
            ",[IpAddress]" +
            ",[LogLevel]" +
            ",[Message]" +
            ",[Source]" +
            ",[StackTrace]" +
            ",[State]" +
            ",[UserId]" +
            ",[OrganisationId]" +
            ",[RequestId]" +
        ")" +
        "VALUES" +
        "(" +
            "@Created" +
            ",@EventId" +
            ",@IpAddress" +
            ",@LogLevel" +
            ",@Message" +
            ",@Source" +
            ",@StackTrace" +
            ",@State" +
            ",@UserId" +
            ",@OrganisationId" +
            ",@RequestId" +
        ")";

    Dictionary<string, object> parameters = new Dictionary<string, object>
    {
        { "@Created", utcNow },
        { "@EventId", eventId.ToString() ?? (object)DBNull.Value },
        { "@IpAddress", ipAddress ?? (object)DBNull.Value },
        { "@LogLevel", logLevel.ToString() ?? (object)DBNull.Value },
        { "@Message", exception?.Message ?? (object)DBNull.Value },
        { "@Source", caller ?? (object)DBNull.Value },
        { "@StackTrace", stackTrace?.Trim() ?? (object)DBNull.Value },
        { "@State", state ?? (object)DBNull.Value },
        { "@UserId", userId ?? (object)DBNull.Value },
        { "@OrganisationId", organisationId ?? (object)DBNull.Value },
        { "@RequestId", requestId ?? (object)DBNull.Value },
    };
    try
    {
        if (_hostingEnvironment.EnvironmentName == "Test")
        {
            using (SqliteConnection sqlConnection = new SqliteConnection($"Data Source={_logAppSettings.ConnectionStrings.Database};Mode=Memory;Cache=Shared;"))
            {
                using (SqliteCommand sqlCommand = new SqliteCommand(query, sqlConnection))
                {
                    foreach (var parameter in parameters)
                    {
                        sqlCommand.Parameters.Add(new SqliteParameter(parameter.Key, parameter.Value));
                    }

                    sqlConnection.Open();

                    await sqlCommand.ExecuteNonQueryAsync();
                }
            }
        }
        else
        {
            using (SqlConnection sqlConnection = new SqlConnection(_logAppSettings.ConnectionStrings.Database))
            {
                using (SqlCommand sqlCommand = new SqlCommand(query, sqlConnection))
                {
                    foreach (var parameter in parameters)
                    {
                        sqlCommand.Parameters.Add(new SqlParameter(parameter.Key, parameter.Value));
                    }

                    sqlConnection.Open();

                    await sqlCommand.ExecuteNonQueryAsync();
                }
            }
        }
    }
    catch (Exception ex)
    {
        ExceptionModel exceptionModel = new ExceptionModel()
        {
            StackTrace = ex?.StackTrace,
            Message = ex?.Message,
            InnerException = ex?.InnerException.ToString()
        };

        LogModel log = new LogModel()
        {
            Created = $"{utcNow:yyyy-MM-dd HH:mm}",
            LogLevel = LogLevel.Error.ToString(),
            EventId = LogEvents.Log,
            Source = ex.Source,
            IpAddress = ipAddress,
            UserId = userId,
            OrganisationId = organisationId,
            State = "An unexpected error occured while trying to insert new exception.",
            Exception = exceptionModel,
            RequestId = requestId
        };

        InsertLog(utcNow, log, categoryAppSettings);
    }
}

如您所见,我正在使用两种不同的数据库类型,两种不同的连接类型。 我真的不喜欢它,因为您必须自定义代码以使测试变得更简单!

两个数据库都可以有一种连接类型吗?

我看过“ Entity SQL”,但是我不认为它在Entity Framework Core中受支持,并且有点过时。

可能不是您想要的,但是您可以通过使用DbConnection而不是SQLConnection避免代码加倍。 您可以在其他任何地方定义DbConnectionType,例如:

Type connectionType = _hostingEnvironment.EnvironmentName == "Test" ? typeof(SqliteConnection) : typeof(SqlConnection);

// If you switch the Connection String outside too, it should work:
string connectionString = _hostingEnvironment.EnvironmentName == "Test" ? $"Data Source={_logAppSettings.ConnectionStrings.Database};Mode=Memory;Cache=Shared;" : _logAppSettings.ConnectionStrings.Database;


        using (DbConnection sqlConnection = Activator.CreateInstance(connectionType, new object[] {connectionString}) as DbConnection)
        {
            using (DbCommand sqlCommand = sqlConnection.CreateCommand())
            {
                sqlCommand.CommandText = query;
                foreach (var parameter in parameters)
                {
                   DbParameter param = sqlCommand.CreateParameter();
                   param.ParameterName= parameter.Key;
                   param.Value=parameter.Value;
                   sqlCommand.Parameters.Add(param );
                }

                sqlConnection.Open();

                await sqlCommand.ExecuteNonQueryAsync();


        }
    }
}

我希望这可以帮助你!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM