C# &引用;“主密钥”的重复条目;在一台机器上,而不是在另一台机器上,使用相同的数据?

C# &引用;“主密钥”的重复条目;在一台机器上,而不是在另一台机器上,使用相同的数据?,c#,mysql,entity-framework,C#,Mysql,Entity Framework,我的问题:插入一组数据在我的本地机器/MySQL数据库上工作,但在生产环境中,它会导致键“PRIMARY”的重复条目出现错误。据我所知,这两种设置是等效的 我的第一个想法是这是一个排序问题,但我检查了两个数据库中的表是否使用了utf8\u bin 表开始是空的,我在代码中执行.Distinct(),因此不应该有任何重复条目 有关表格: CREATE TABLE `mytable` ( `name` varchar(100) CHARACTER SET utf8 NOT NULL, `ap

我的问题:插入一组数据在我的本地机器/MySQL数据库上工作,但在生产环境中,它会导致键“PRIMARY”的重复条目出现错误。据我所知,这两种设置是等效的

我的第一个想法是这是一个排序问题,但我检查了两个数据库中的表是否使用了
utf8\u bin

表开始是空的,我在代码中执行
.Distinct()
,因此不应该有任何重复条目

有关表格:

CREATE TABLE `mytable` (
  `name` varchar(100) CHARACTER SET utf8 NOT NULL,
  `appid` int(11) NOT NULL,
  -- A few other irrelevant fields
  PRIMARY KEY (`name`,`appid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
Database.cs

[DbConfigurationType(typeof(MySql.Data.Entity.MySqlEFConfiguration))]
public class Database : DbContext
{
    public DbSet<MyTable> MyTable { get; set; }
    public static Database Get()
    {
        /* Not important */
    }
    //etc.
}
[Table("mytable")]
public class MyTable : IEquatable<MyTable>, IComparable, IComparable<MyTable>
{
    [Column("name", Order = 0), Key, Required, DatabaseGenerated(DatabaseGeneratedOption.None)]
    public string Name
    {
        get { return _name; }
        set { _name = value.Trim().ToLower(); }
    }

    private string _name;

    [Column("appid", Order = 1), Key, Required, DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int ApplicationId { get; set; }

    //Equals(), GetHashCode(), CompareTo(), ==() etc. all auto-generated by Resharper to use both Name and ApplicationId.
    //Have unit-tests to verify they work correctly.
}
然后使用它:

using(Database db = Database.Get())
using(DbContextTransaction transaction = db.Database.BeginTransaction(IsolationLevel.ReadUncommitted))
{
    IEnumerable<MyTable> newEntries = GetNewEntries();
    //Verify no existing entries already in the table; not necessary to show since table is empty anyways
    db.MyTable.AddRange(newEntries.Distinct());
}
使用(Database db=Database.Get())
使用(DbContextTransaction事务=db.Database.BeginTransaction(IsolationLevel.ReadUncommitted))
{
IEnumerable newEntries=GetNewEntries();
//验证表中是否已存在任何条目;无需显示,因为表始终为空
db.MyTable.AddRange(newEntries.Distinct());
}

在使用
utf8\u bin
时,在代码中执行
.Distinct()
之后,我不知道数据库中怎么会有重复的条目,特别是因为它在一台机器上工作,而在另一台机器上却不工作。有人有什么想法吗?

我最终通过unicode转义非ascii字符解决了这个问题,类似于


但是,我仍然不知道为什么会发生这种情况…

这两台机器都使用相同的数据库驱动程序吗?当安装了不同的驱动程序时,我在EF和Oracle方面也遇到过类似的问题

编辑:

本文件

表示在MySQL 5.5.3之前,Unicode字符最多使用每个字符3个字节进行存储,而在MySQL 5.5.3之前,Unicode字符最多使用4个字节进行存储。这可以解释密钥是否被确定为唯一的差异。当使用“补充字符”时,这种差异就会发挥作用,因为旧版本根本无法存储这些字符


您的两个数据库是否处于不同的领域(MySQL 5.5.3)?

我将研究以下几点:

  • 在两台机器上检查MySQL的确切版本。您可以在MySQL客户机中使用
    显示变量,如“%version%”
  • 使用
    选择十六进制(名称)
    查看重复行的数据编码方式
  • 调查“utf8”数据是否存储在utf8mb3或utf8mb4中

假设在dev机器上,数据是从新安装插入的,而在生产机器上,数据可能是使用较旧版本插入的,然后服务器升级,我会特别检查是否需要(并且已经完成)正确完成升级过程

特别是,请参阅MySQL参考手册中的以下章节(有关正确版本):

如有必要,重新生成索引

编辑(2016-10-12)

以上所有内容都集中在表和存储上

另一个要检查的部分是客户端和服务器之间的连接,使用诸如
character\u set\u connection
之类的变量

请检查所有与字符集相关的系统变量,以进行比较

mysql> show variables like "%character%";
+--------------------------+-------------------------------------------+
| Variable_name            | Value                                     |
+--------------------------+-------------------------------------------+
| character_set_client     | utf8                                      |
| character_set_connection | utf8                                      |
| character_set_database   | latin1                                    |
| character_set_filesystem | binary                                    |
| character_set_results    | utf8                                      |
| character_set_server     | latin1                                    |
| character_set_system     | utf8                                      |
| character_sets_dir       | /home/malff/GIT_TRUNK/sql/share/charsets/ |
+--------------------------+-------------------------------------------+
8 rows in set (0.02 sec)

我认为这可能是因为某些字符根据环境具有不同的含义,所以通常建议在将字符串用作数据值之前对这些特殊字符进行转义


查看此信息:

有关
独特的
:;)的相关问题。可能与当前运行此代码的机器的文化有关。字符串相等性比较取决于当前区域性,因此Distinct可以在不同的服务器上产生不同的结果。然后,.NET认为与当前区域性不同的名称被mysql认为是相同的,您会得到冲突。因此,请尝试检查两台机器的语言设置,如果确实存在问题,请在字符串比较中使用相同的区域性。您能给出一个未提交值的示例吗?来自两台计算机。@Evk Yes我验证了两台计算机使用的是相同的
CultureInfo.CurrentCulture
@Som仅在服务器上被视为重复的示例字符串:
autograph:啸天
调用AddRange之前newEntries.Distinct()返回的项目数在两台计算机上是否相同?相同的驱动程序,但不同的数据库版本。可能是MySQL的错误被修复了?在我的例子中,在一台机器上运行Oracle12驱动程序,在另一台机器上运行Oracle11驱动程序来对抗Oracle11g,这导致了数字处理方式的差异。一个设置返回int,另一个返回long。如果可能,您应该在本地和测试/生产环境中运行相同的版本。重新编辑:根据该链接,4字节UTF8字符使用新的字符集存储,
utf8mb4
。正如您所说,他们没有更改我的两个数据库使用的
utf8
字符集。它显示:"... 从MySQL 5.5.3开始,utf8mb4字符集每个字符最多使用四个字节,支持补充字符:。。。对于补充字符,utf8根本无法存储该字符,而utf8mb4需要四个字节来存储该字符。因为utf8根本无法存储字符,所以在utf8列中没有补充字符,并且在从MySQL的旧版本升级utf8数据时不必担心转换字符或丢失数据。“是的,但我根本没有使用
utf8mb4
。两个数据库都使用
utf8\u bin
,数据正确插入其中一个数据库。?在任何情况下,这都不会成为问题。EF驱动程序应该透明地转义任何可能导致问题的字符。它应该。现在,是吗?我建议你尝试几件事,只是为了排除它。1) 在你的钥匙上进行手动区分,2)在钥匙上寻找特殊字符。看看你是否能找到一些,然后使用这些值运行一个快速测试,看看它是否有问题。可能是因为