C # Sqlite «ограничение не удалось» - PullRequest
0 голосов
/ 10 мая 2018

У меня есть BindingList, который является источником данных DataGridView.Я хочу использовать SqliteDataAdapter + SqliteCommandBuilder , чтобы упростить загрузку / сохранение в моей базе данных Sqlite, но поскольку в SqliteDataAdapter.Fill / Update оба принимают только DataTable или DataSet в качестве параметра, я использую методы расширения дляпреобразовать мой BindingList в / из DataTable.

При этом, если я обновляю некоторые значения в своем BindingList, а затем пытаюсь обновить БД, я получаю УНИКАЛЬНОЕ исключение из условия ограничения.Я не совсем уверен, почему мой SqliteDataAdapter пытается выполнить вставки, а не обновления, учитывая, что никакие значения не были добавлены, только обновлены.

Я мог бы DELETE * from the table перед вызовом adapter.Update, но это не похожеидеально или правильно.

Как правильно достичь моей цели (возможность использовать адаптер. Заполнить / обновить с помощью общего списка)?

public void LoadDatabase()
{
    using (var conn = new SQLiteConnection(dbConnectionString))
    {
        using (var adapter = new SQLiteDataAdapter("SELECT * FROM proxies", conn))
        {
            var table = new DataTable();
            adapter.Fill(table);
            var list = new BindingList<Proxy>(table.ConvertTo<Proxy>());
            foreach (var item in list)
            {
                proxies.Add(item);
            }
        }
    }
}

public void SaveDatabase()
{
    using (var conn = new SQLiteConnection(dbConnectionString))
    {
        using (var adapter = new SQLiteDataAdapter("SELECT * FROM proxies", conn))
        {
            using (var builder = new SQLiteCommandBuilder(adapter))
            {
                adapter.InsertCommand = builder.GetInsertCommand();
                adapter.DeleteCommand = builder.GetDeleteCommand();
                adapter.UpdateCommand = builder.GetUpdateCommand();
                var table = proxies.ToDataTable();
                adapter.Update(table);

            }
        }
    }
}

Используемые методы расширения:

public static List<T> ConvertTo<T>(this DataTable datatable) where T : new()
{
    List<T> Temp = new List<T>();
    try
    {
        List<string> columnsNames = new List<string>();
        foreach (DataColumn DataColumn in datatable.Columns)
            columnsNames.Add(DataColumn.ColumnName);
        Temp = datatable.AsEnumerable().ToList().ConvertAll<T>(row => getObject<T>(row, columnsNames));
        return Temp;
    }
    catch
    {
        return Temp;
    }

}
public static T getObject<T>(DataRow row, List<string> columnsName) where T : new()
{
    T obj = new T();
    try
    {
        string columnname = "";
        string value = "";
        PropertyInfo[] Properties;
        Properties = typeof(T).GetProperties();
        foreach (PropertyInfo objProperty in Properties)
        {
            columnname = columnsName.Find(name => name.ToLower() == objProperty.Name.ToLower());
            if (!string.IsNullOrEmpty(columnname))
            {
                value = row[columnname].ToString();
                if (!string.IsNullOrEmpty(value))
                {
                    if (objProperty.PropertyType.IsEnum)
                    {
                        objProperty.SetValue(obj, Enum.Parse(objProperty.PropertyType, value));
                    }
                    else
                    {
                        if (Nullable.GetUnderlyingType(objProperty.PropertyType) != null)
                        {
                            value = row[columnname].ToString().Replace("$", "").Replace(",", "");
                            objProperty.SetValue(obj, Convert.ChangeType(value, Type.GetType(Nullable.GetUnderlyingType(objProperty.PropertyType).ToString())), null);
                        }
                        else
                        {
                            value = row[columnname].ToString().Replace("%", "");
                            objProperty.SetValue(obj, Convert.ChangeType(value, Type.GetType(objProperty.PropertyType.ToString())), null);
                        }
                    }
                }
            }
        }
        return obj;
    }
    catch
    {
        return obj;
    }
}

public static DataTable ToDataTable<T>(this IList<T> data)
{
    PropertyDescriptorCollection properties =
        TypeDescriptor.GetProperties(typeof(T));
    DataTable table = new DataTable();
    foreach (PropertyDescriptor prop in properties)
        table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
    foreach (T item in data)
    {
        DataRow row = table.NewRow();
        foreach (PropertyDescriptor prop in properties)
            row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
        table.Rows.Add(row);
    }
    return table;
}

1 Ответ

0 голосов
/ 10 мая 2018

Я решил просто удалить все записи перед выполнением адаптера. Обновление (), это самое простое решение, которое я смог придумать. Если у кого-то есть идея получше, скажите.

public void SaveDatabase()
{
    using (var conn = new SQLiteConnection(dbConnectionString))
    {
        using (var adapter = new SQLiteDataAdapter("SELECT * FROM proxies", conn))
        {
            using (var builder = new SQLiteCommandBuilder(adapter))
            {
                conn.Open();
                using (var cmd = new SQLiteCommand("DELETE FROM proxies", conn))
                {
                    cmd.ExecuteNonQuery();
                }
                adapter.InsertCommand = builder.GetInsertCommand();
                adapter.DeleteCommand = builder.GetDeleteCommand();
                adapter.UpdateCommand = builder.GetUpdateCommand();
                var table = proxies.ToDataTable();
                adapter.Update(table);

            }
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...