【问题标题】:C# Sqlite Parameter Working/Not working in different pagesC# Sqlite 参数工作/不工作在不同的页面
【发布时间】:2018-09-16 22:44:01
【问题描述】:

第一次发帖。我正在为我的一个小项目尝试 sqlite,我遇到了一些非常奇怪的事情。问题似乎出在参数上,但我不明白。也许这里有人可以解释为什么它在某个地方有效,但在另一个地方无效。

就是这样:在这段代码中,一切都运行良好:

    public void SaveObject(PlayerCharacter playerCharacter)
    {
        SQLiteConnection sqliteConnection = new SQLiteConnection(ConnectionString.Connection);
        sqliteConnection.Open();

        String query = String.Empty;

        switch (playerCharacter.InternalState)
        {
            case InternalStates.New:
                query = "INSERT INTO PlayerCharacters(Id, Name, ArmorClass, InitiativeBonus) VALUES (@Id, @Name, @ArmorClass, @InitiativeBonus)";
                break;

            case InternalStates.Modified:
                query = @"  UPDATE PlayerCharacters
                            SET Name = @Name,
                                ArmorClass = @ArmorClass,
                                InitiativeBonus = @InitiativeBonus
                            WHERE Id = @Id";
                break;

            case InternalStates.Deleted:
                //To maybe implement in the future
                break;
        }

        List<SQLiteParameter> parameters = new List<SQLiteParameter>()
        {
            new SQLiteParameter("@Id", playerCharacter.Id),
            new SQLiteParameter("@Name", playerCharacter.Name),
            new SQLiteParameter("@ArmorClass", playerCharacter.ArmorClass),
            new SQLiteParameter("@InitiativeBonus", playerCharacter.InitiativeBonus)
        };

        SQLiteCommand command = new SQLiteCommand(query, sqliteConnection);
        command.Parameters.AddRange(parameters.ToArray());

        command.ExecuteNonQuery();

        playerCharacter.SetInternalState(InternalStates.UnModified, true);

        sqliteConnection.Close();
    }

在这里我试图隔离问题。当我删除参数IdWhere 子句时,一切都会按原样更新,但是当我尝试使用参数时,它永远找不到要更新的行:

    public void SaveObject(Monster monster)
    {
        SQLiteConnection sqliteConnection = new SQLiteConnection(ConnectionString.Connection);
        sqliteConnection.Open();

        String query = String.Empty;

        switch (monster.InternalState)
        {
            case InternalStates.New:
                query = @"  INSERT INTO Monsters(Id,
                                                Name,
                                                Size,
                                                Type,
                                                Subtype,
                                                Alignment,
                                                ArmorClass,
                                                HitPoints,
                                                HitDice,
                                                Speed,
                                                DamageVulnerabilities,
                                                DamageResistances,
                                                DamageImmunities,
                                                ConditionImmunities,
                                                Senses,
                                                Languages,
                                                ChallengeRating) 
                            VALUES (@Id,
                                    @Name,
                                    @Size,
                                    @Type,
                                    @Subtype,
                                    @Alignment,       
                                    @ArmorClass,
                                    @HitPoints,
                                    @HitDice,
                                    @Speed,
                                    @DamageVulnerabilities,
                                    @DamageResistances,
                                    @DamageImmunities,
                                    @ConditionImmunities,
                                    @Senses,
                                    @Languages,
                                    @ChallengeRating)";
                break;

            case InternalStates.Modified:
                query = @"  UPDATE Monsters
                            SET Name = @Name
                            WHERE Monsters.Id = @Id";

                //Size = @Size,
                //                Type = @Type,
                //                Subtype = @Subtype,
                //                Alignment = @Alignment,
                //                ArmorClass = @ArmorClass,
                //                HitPoints = @HitPoints,
                //                HitDice = @HitDice,
                //                Speed = @Speed,
                //                DamageVulnerabilities = @DamageVulnerabilities,
                //                DamageResistances = @DamageResistances,
                //                DamageImmunities = @DamageImmunities,
                //                ConditionImmunities = @ConditionImmunities,
                //                Senses = @Senses,
                //                Languages = @Languages,
                //                ChallengeRating = @ChallengeRating
                break;

            case InternalStates.Deleted:
                //To maybe implement in the future
                break;
        }

        List<SQLiteParameter> parameters = new List<SQLiteParameter>()
        {
            new SQLiteParameter("@Id", monster.Id ),
            new SQLiteParameter("@Name", monster.Name)
            //new SQLiteParameter("@Size", monster.Size),
            //new SQLiteParameter("@Type", monster.Type),
            //new SQLiteParameter("@Subtype", monster.Subtype),
            //new SQLiteParameter("@Alignment", monster.Alignment),
            //new SQLiteParameter("@ArmorClass", monster.ArmorClass),
            //new SQLiteParameter("@HitPoints", monster.HitPoints),
            //new SQLiteParameter("@HitDice", monster.HitDice),
            //new SQLiteParameter("@Speed", monster.Speed),
            //new SQLiteParameter("@DamageVulnerabilities", monster.DamageVulnerabilities),
            //new SQLiteParameter("@DamageResistances", monster.DamageResistances),
            //new SQLiteParameter("@DamageImmunities", monster.DamageImmunities),
            //new SQLiteParameter("@ConditionImmunities", monster.ConditionImmunities),
            //new SQLiteParameter("@Senses", monster.Senses),
            //new SQLiteParameter("@Languages", monster.Languages),
            //new SQLiteParameter("@ChallengeRating", monster.ChallengeRating)
        };

        SQLiteCommand command = new SQLiteCommand(query, sqliteConnection);
        command.Parameters.AddRange(parameters.ToArray());

        int i = command.ExecuteNonQuery();

        monster.SetInternalState(InternalStates.UnModified, true);

        sqliteConnection.Close();
    }

我已经检查过并且该 ID 存在于数据库中。它应该找到一个结果。 如果有人知道原因并可以向我解释,那会让我很开心!

更新

我仍然不知道为什么它在第一个示例中有效,而在另一个示例中无效,但这里的解决方案对我有用。

sql 参数有一个 DbType 属性,它会自动设置为适合该值,在我的例子中它设置为 Guid。在 Sqlite 中,uniqueidentifier 类型不存在,它像字符串一样处理。所以这就是我所做的:

        ...

        List<SQLiteParameter> parameters = new List<SQLiteParameter>()
        {
            new SQLiteParameter("@Id", monster.Id ) {DbType = DbType.String},
            new SQLiteParameter("@Name", monster.Name)
            //new SQLiteParameter("@Size", monster.Size),
            //new SQLiteParameter("@Type", monster.Type),
            //new SQLiteParameter("@Subtype", monster.Subtype),
            //new SQLiteParameter("@Alignment", monster.Alignment),
            //new SQLiteParameter("@ArmorClass", monster.ArmorClass),
            //new SQLiteParameter("@HitPoints", monster.HitPoints),
            //new SQLiteParameter("@HitDice", monster.HitDice),
            //new SQLiteParameter("@Speed", monster.Speed),
            //new SQLiteParameter("@DamageVulnerabilities", monster.DamageVulnerabilities),
            //new SQLiteParameter("@DamageResistances", monster.DamageResistances),
            //new SQLiteParameter("@DamageImmunities", monster.DamageImmunities),
            //new SQLiteParameter("@ConditionImmunities", monster.ConditionImmunities),
            //new SQLiteParameter("@Senses", monster.Senses),
            //new SQLiteParameter("@Languages", monster.Languages),
            //new SQLiteParameter("@ChallengeRating", monster.ChallengeRating)
        };

        ...

【问题讨论】:

  • Monsters表中ID字段的SQL类型是什么?
  • 代码中的Guid,表列是唯一标识符

标签: c# sqlite sqlite-net


【解决方案1】:

您可以尝试更改此设置吗:

UPDATE Monsters
SET Name = @Name
WHERE Monsters.Id = @Id

UPDATE Monsters SET Name = @Name
WHERE Monsters.Id like @Id

在 C# 中:

    new SQLiteParameter("@Id", "%" + monster.Id + "%");

现在,您必须在 switch/case 语句上方声明列表:

 List<SQLiteParameter> parameters = new List<SQLiteParameter>()
        {
            // remove the @id parameter here
            new SQLiteParameter("@Name", monster.Name)
            //new SQLiteParameter("@Size", monster.Size),
            //new SQLiteParameter("@Type", monster.Type),
            //new SQLiteParameter("@Subtype", monster.Subtype),
            //new SQLiteParameter("@Alignment", monster.Alignment),
            //new SQLiteParameter("@ArmorClass", monster.ArmorClass),
            //new SQLiteParameter("@HitPoints", monster.HitPoints),
            //new SQLiteParameter("@HitDice", monster.HitDice),
            //new SQLiteParameter("@Speed", monster.Speed),
            //new SQLiteParameter("@DamageVulnerabilities", monster.DamageVulnerabilities),
            //new SQLiteParameter("@DamageResistances", monster.DamageResistances),
            //new SQLiteParameter("@DamageImmunities", monster.DamageImmunities),
            //new SQLiteParameter("@ConditionImmunities", monster.ConditionImmunities),
            //new SQLiteParameter("@Senses", monster.Senses),
            //new SQLiteParameter("@Languages", monster.Languages),
            //new SQLiteParameter("@ChallengeRating", monster.ChallengeRating)
        };

在你的情况下插入:

parameters.Add(new SQLiteParameter("@Id", monster.Id ));

在你的情况下更新:

parameters.Add(new SQLiteParameter("@Id", "%" + monster.Id + "%"));

你的最终代码:

public void SaveObject(Monster monster)
{
    SQLiteConnection sqliteConnection = new SQLiteConnection(ConnectionString.Connection);
    sqliteConnection.Open();

    String query = String.Empty;
    List<SQLiteParameter> parameters = new List<SQLiteParameter>()
    {
        new SQLiteParameter("@Name", monster.Name)
        //new SQLiteParameter("@Size", monster.Size),
        //new SQLiteParameter("@Type", monster.Type),
        //new SQLiteParameter("@Subtype", monster.Subtype),
        //new SQLiteParameter("@Alignment", monster.Alignment),
        //new SQLiteParameter("@ArmorClass", monster.ArmorClass),
        //new SQLiteParameter("@HitPoints", monster.HitPoints),
        //new SQLiteParameter("@HitDice", monster.HitDice),
        //new SQLiteParameter("@Speed", monster.Speed),
        //new SQLiteParameter("@DamageVulnerabilities", monster.DamageVulnerabilities),
        //new SQLiteParameter("@DamageResistances", monster.DamageResistances),
        //new SQLiteParameter("@DamageImmunities", monster.DamageImmunities),
        //new SQLiteParameter("@ConditionImmunities", monster.ConditionImmunities),
        //new SQLiteParameter("@Senses", monster.Senses),
        //new SQLiteParameter("@Languages", monster.Languages),
        //new SQLiteParameter("@ChallengeRating", monster.ChallengeRating)
    };

    switch (monster.InternalState)
    {
        case InternalStates.New:
            query = @"  INSERT INTO Monsters(Id,
                                            Name,
                                            Size,
                                            Type,
                                            Subtype,
                                            Alignment,
                                            ArmorClass,
                                            HitPoints,
                                            HitDice,
                                            Speed,
                                            DamageVulnerabilities,
                                            DamageResistances,
                                            DamageImmunities,
                                            ConditionImmunities,
                                            Senses,
                                            Languages,
                                            ChallengeRating) 
                        VALUES (@Id,
                                @Name,
                                @Size,
                                @Type,
                                @Subtype,
                                @Alignment,       
                                @ArmorClass,
                                @HitPoints,
                                @HitDice,
                                @Speed,
                                @DamageVulnerabilities,
                                @DamageResistances,
                                @DamageImmunities,
                                @ConditionImmunities,
                                @Senses,
                                @Languages,
                                @ChallengeRating)";
                parameters.Add(new SQLiteParameter("@Id", monster.Id ));
            break;

        case InternalStates.Modified:
            query = @"  UPDATE Monsters
                        SET Name = @Name
                        WHERE Monsters.Id like @Id";

            //Size = @Size,
            //                Type = @Type,
            //                Subtype = @Subtype,
            //                Alignment = @Alignment,
            //                ArmorClass = @ArmorClass,
            //                HitPoints = @HitPoints,
            //                HitDice = @HitDice,
            //                Speed = @Speed,
            //                DamageVulnerabilities = @DamageVulnerabilities,
            //                DamageResistances = @DamageResistances,
            //                DamageImmunities = @DamageImmunities,
            //                ConditionImmunities = @ConditionImmunities,
            //                Senses = @Senses,
            //                Languages = @Languages,
            //                ChallengeRating = @ChallengeRating
            parameters.Add(new SQLiteParameter("@Id", "%" + monster.Id + "%"));
            break;

        case InternalStates.Deleted:
            //To maybe implement in the future
            break;
    }

    SQLiteCommand command = new SQLiteCommand(query, sqliteConnection);
    command.Parameters.AddRange(parameters.ToArray());

    int i = command.ExecuteNonQuery();

    monster.SetInternalState(InternalStates.UnModified, true);

    sqliteConnection.Close();
}

更新:

sqllite 不支持 GUId。将 Guid 转换为字符串或将 id 的数据类型更改为字符串可能会对您有所帮助。

看这里:

SQLite Parameter Issue with Guids

【讨论】:

  • 嗯,它工作。但为什么 ? id 是一个 Guid,添加时应该正确格式化它有一个参数 no ?为什么与其他对象一起工作正常?
  • 更新和插入不适用于上述更改
  • 尝试在 switch/case 语句上方声明参数列表。参数列表不包含@id 参数
  • 我已对您的代码进行了更改以适应插入/更新。我们稍后会谈到“为什么会这样”
  • 我理解您的回答,但这不是我正在寻找的解决方案。感觉更像是一个补丁而不是解决方案。但是你让我意识到了一些事情。类型 guid 是否可能在 sqlite 中不存在并且像 String 一样处理?
猜你喜欢
  • 1970-01-01
  • 2013-01-18
  • 1970-01-01
  • 2011-01-26
  • 1970-01-01
  • 1970-01-01
  • 2014-01-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多