簡體   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