c# - 将特殊字符分配给字符串时,Razor 页面会弄乱编码

标签 c# mysql razor entity-framework-core special-characters

更新 4:

哦哇,显然这不是 EF 或配置问题。

Somehow the .razor page variable assigment is messing up the data.

现在不知道如何继续处理这个问题,但我至少编辑了标题以反射(reflect)当前问题:Razor 页面在为字符串分配特殊字符时弄乱了编码。


问题:

无论我做什么,插入 MySQL 5.7.17 数据库的字符始终显示为 �:

Database lookup

尽管有类似的帖子,但没有一个解决方案对我有用,而且我已经耗尽了我的研究能力。

我尝试过的:

代码:

连接字符串:

"MySQL": "server=localhost;user=root;database=sgn;charset=utf8mb4;"

用户模型.cs

namespace source.Data.Models
{
    [MySqlCharset("utf8mb4")]
    [MySqlCollation("utf8mb4_unicode_ci")]
    public class UserModel
    {
        public UserModel() { }

        [Key]
        public long Id { get; set; }
        [MySqlCharset("utf8mb4")]
        [MySqlCollation("utf8mb4_unicode_ci")]
        public string Username { get; set; }
        public string Email { get; set; }
        public string Password { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Language { get; set; }
        public string StartPage { get; set; }
    }
}

DatabaseContext.cs

namespace source.Data.Database
{
    public class DatabaseContext : DbContext
    {
        private IConfiguration Configuration;
        public DbSet<UserModel> Users { get; set; }

        public DatabaseContext(DbContextOptions<DatabaseContext> options, IConfiguration configuration)
            : base(options)
        {
            Configuration = configuration;
        }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder
                .UseMySQL(Configuration.GetSection("AppSettings").GetSection("Database").GetSection("ConnectionString")["MySQL"]);
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<UserModel>().Property(p => p.Username).IsUnicode(true);
            base.OnModelCreating(modelBuilder);
        }

    }
}

DesignTimeDatabaseContextFactory.cs

namespace source.Data.Database
{
    public class DesignTimeDatabaseContextFactory : IDesignTimeDbContextFactory<DatabaseContext>
    {
        private IConfiguration Configuration;
        private AppSettingsService AppSettings;

        public DesignTimeDatabaseContextFactory()
        {
        }

        public DesignTimeDatabaseContextFactory(IConfiguration configuration, AppSettingsService appSettings)
        {
            Configuration = configuration;
            AppSettings = appSettings;
        }

        public DatabaseContext CreateDbContext(string[] args)
        {
            var builder = new DbContextOptionsBuilder<DatabaseContext>();

            builder.UseMySQL(AppSettings.ConnectionString);


            return new DatabaseContext(builder.Options, Configuration);
        }
    }
}

Create.razor - 这是我将用户添加到数据库的位置。请注意,该项目使用 Blazor,因此不要被“@functions”标签混淆。这两个函数都没有正确添加数据,注释是我尝试过的准备好的语句。

<div class="login_form">
    <h3>Create Account</h3>

    <button @onclick="@(e => AddEntry())">Add DB User!</button><br />
    <button @onclick="@(e => AddEntry2())">Add TEST!</button><br />
</div>

@functions {

    void AddEntry2()
    {
        UserModel test = new UserModel();

        test.Username = "Test çã";
        test.FirstName = "Michel";
        test.LastName = "Arendt";
        test.Email = "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="fd909c9491bd9a909c9491d39e9290" rel="noreferrer noopener nofollow">[email protected]</a>";
        test.Password = "123";
        test.Language = "pt-BR";
        test.StartPage = "/Home/";

        db.Database.ExecuteSqlCommand("SET NAMES utf8mb4");
        db.Database.ExecuteSqlCommand("SET character_set_connection = utf8mb4");
        db.Database.ExecuteSqlCommand("INSERT INTO Users (Username) VALUES (N'" + test.Username + "')");
        db.SaveChanges();


        //using (SqlConnection connection = new SqlConnection(AppSettings.DatabaseConnectionString()))
        //{
        //    connection.Open();
        //    SqlCommand command = new SqlCommand(null, connection);

        //    // Create and prepare an SQL statement.
        //    command.CommandText =
        //        "INSERT INTO Users (Username) " +
        //        "VALUES (@username)";
        //    SqlParameter username = new SqlParameter("@username", SqlDbType.NVarChar, 100);
        //    username.Value = "Garçon";
        //    command.Parameters.Add(username);

        //    // Call Prepare after setting the Commandtext and Parameters.
        //    command.Prepare();
        //    command.ExecuteNonQuery();
        //}
    }

    void AddEntry()
    {
        UserModel waitress = new UserModel();

        waitress.Username = "Garçon";
        waitress.FirstName = "Test";
        waitress.LastName = "Test";
        waitress.Email = "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="5835393134183f35393134763b3735" rel="noreferrer noopener nofollow">[email protected]</a>";
        waitress.Password = "123";
        waitress.Language = "pt-BR";
        waitress.StartPage = "/Home/";

        db.Users.Add(waitress);
        db.SaveChanges();
    }
}

source.csproj(依赖项引用)

<Project Sdk="Microsoft.NET.Sdk.Web">
  <PropertyGroup>
    <TargetFramework>netcoreapp3.0</TargetFramework>
    <LangVersion>7.3</LangVersion>
    <RestorePackages>false</RestorePackages>
    <Version>0.10.0</Version>
    <Authors>Michel Arendt</Authors>
    <Product>SGN</Product>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <DebugType>full</DebugType>
    <DebugSymbols>true</DebugSymbols>
  </PropertyGroup>
  <ItemGroup>
    <Content Remove="compilerconfig.json" />
  </ItemGroup>
  <ItemGroup>
    <None Include="compilerconfig.json" />
  </ItemGroup>
  <ItemGroup>
    <PackageReference Include="ElectronNET.API" Version="5.22.13" />
    <PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.2.4" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="2.2.4" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="2.2.4">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
    <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.2.0" />
    <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.0.0-preview6.19304.6" />
    <PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.2.0" />
    <PackageReference Include="MySql.Data.EntityFrameworkCore" Version="8.0.16" />
    <PackageReference Include="System.Configuration.ConfigurationManager" Version="4.5.0" />
  </ItemGroup>
  <ItemGroup>
    <Content Update="electron.manifest.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </Content>
  </ItemGroup>
</Project>

数据库配置

数据库和列的默认排序规则和字符集分别为 utf8mb4_unicode_ci 和 utf8mb4:

Default database character set and collation

Columns character set and collation


关于我还可以尝试什么来解决这个问题或者我犯了什么错误,有什么想法吗?

提前致谢!


更新:

我按照 Bradley Grainger(评论)的建议切换到 Pomelo.EntityFrameworkCore.MySql,但这无助于解决问题。我更改的文件现在是:

Startup.csDesignTimeDatabaseContextFactory.cs 的构建更改为使用:

builder
                .UseMySql(AppSettings.ConnectionString,
                    mysqlOptions =>
                    {
                        mysqlOptions
                            .CharSetBehavior(CharSetBehavior.AppendToAllColumns)
                            .AnsiCharSet(CharSet.Utf8mb4)
                            .UnicodeCharSet(CharSet.Utf8mb4);
                    });

创建.razor

void AddEntry2()
{
    UserModel test = new UserModel();

    test.Username = "Test çã";
    test.FirstName = "Michel";
    test.LastName = "Arendt";
    test.Email = "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="523f333b3e12353f333b3e7c313d3f" rel="noreferrer noopener nofollow">[email protected]</a>";
    test.Password = "123";
    test.Language = "pt-BR";
    test.StartPage = "/Home/";

    using (MySqlConnection connection = new MySqlConnection(AppSettings.ConnectionString))
    {
        connection.Open();
        MySqlCommand command = new MySqlCommand(null, connection);

        // Create and prepare an SQL statement.
        command.CommandText =
            "INSERT INTO Users (Username) " +
            "VALUES (@username)";
        MySqlParameter username = new MySqlParameter("@username", MySqlDbType.LongText, 100);
        username.Value = "Garçon";
        command.Parameters.Add(username);

        // Call Prepare after setting the Commandtext and Parameters.
        command.Prepare();
        command.ExecuteNonQuery();
    }
}

认为这会有所帮助,因此我还在本地服务器上设置了 MySQL 初始化 (my.ini):

[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_general_ci

但是,没有任何效果。还有其他想法吗?


更新2:

为了确定这是数据库问题还是 EF Core 问题,我设置了一个简单的 PHP 脚本来在数据库中插入相同的条目。

On this image entry 1 and 2 are inserted from EF Core while entry 3 was inserted from PHP

从图像中可以看出,数据库看起来很好,因为 PHP 的插入工作正常。

如何确保 EF Core 在添加条目时使用“utf8mb4”编码?


最佳答案

正如 Thomas Schmidt 在 OP 评论中所建议的那样,问题出在其他地方,我没有想到 Visual Studio 保存文件所用的编码。关于这个问题的解决方案是这样描述的:

razor view » character rendered as »

解决方案:

选择您要更改编码的文件,然后点击文件菜单,然后将“页面”另存为,然后选择Save with Encoding...并选择所需的编码。


我编辑了帖子的问题标题以反射(reflect)当前问题。让我知道是否应该将其改回来,因为我不确定如何继续。

关于c# - 将特殊字符分配给字符串时,Razor 页面会弄乱编码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56955235/

相关文章:

c# - 在对象初始值设定项中迭代列表

c# - .NetCore 2.0 - MVC View 错误 - IEnumerable

PHP 在 POST 之前重新格式化日期

php - 更新 mysql 数据库中所有列的脚本

c# - 使用新的 RazorEngine API 进行模板化

c# - 如何处理 SilverLight 4 和 WPF 应用程序的 WCF 身份验证

c# - Entity Framework 4.2“该类型不具有 EdmEntityTypeAttribute 属性,但包含在具有 EdmSchemaAttribute 属性的程序集中

MYSQL Count group by rows 忽略 JOIN 和 SUM 字段对 Joined 表的影响

javascript - CSS- jQuery - 将一个 div 向左滚动,同时将另一个 div 扩展到宽度 100%

asp.net-mvc - foreach 中 switch 语句的正确 Razor 语法