Как я могу запросить Sqlite в Xamarin с помощью Entity Framework?

#c# #sqlite #xamarin.forms #entity-framework-6

#c# #sqlite #xamarin.forms #entity-framework-6

Вопрос:

Я в Xamarin.Проект Forms (C #) с использованием плагина Sqlite и EF (Microsoft.Entityframeworkcore.sqlite). Что происходит, зависит:

Сценарий 1: я использую «Базу данных.EnsureDeletedAsync»

  • Я могу поместить данные в БД
  • в пределах одного и того же оператора «using» и объекта «DbContext» я могу получить данные с помощью запроса LINQ без ошибок.

Сценарий 2: я не использую «Базу данных.EnsureDeletedAsync»

  • база данных уже существует
  • Я могу добавить к нему данные
  • в пределах одного и того же оператора «using» и объекта «DbContext» любая попытка получить данные с помощью запроса LINQ (я пробовал несколько способов) приводит к ошибке (исключение System.NullReferenceException: ссылка на объект не установлена для экземпляра объекта).

В ОБОИХ сценариях я могу извлечь ADB из базы данных из эмулятора Android и проверить

1) база данных существует, и 2) мои данные поступают в нее.

К вашему сведению — путь к базе данных проверяется на правильность (опять же, я могу извлечь базу данных и просмотреть в ней данные).

 // POCO class

public class Participant
{
        [Key]
        public int Id { get; set; }
        public string Fname { get; set; }
}


// DB Context

public class DatabaseContext : DbContext
{
        string _dbPath;

        public DbSet<Participant> Participants { get; set; }

        public DatabaseContext(string dbPath)
        {
            _dbPath = dbPath;

            //Database.EnsureDeletedAsync();
            //Database.EnsureCreatedAsync();
        }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlite($"Filename={_dbPath}");
        }
}


// Main page code-behind

InitializeComponent ();

// Create Database amp; Tables
using (var db = new DatabaseContext(App.DbPath))
{
    // Insert Data
    db.Add(new Participant() { Fname = "time: "   DateTime.Now.ToString() });
    db.SaveChanges();

    // Retrieve Data
    // Next two lines receive error in scenario 2
    var result2 = db.Participants.Where(xyz => xyz.Id == 1).ToList();
    IEnumerable<Participant> p = db.Participants.ToList();
}
  

Комментарии:

1. вам нужно определить, какая конкретная часть инструкции вызывает нулевую ссылку.

2. Я сделал. Это в области кода, внизу.

3. Не строка кода, часть которой является нулевой. Это участники? Или предложение Where? Или что-то еще? Затем выясните, почему это значение равно null.

4. Хорошо, итак, я разбил строку «result2» на две строки. Исключение генерируется во второй строке. Я могу навести курсор мыши и увидеть, что 1) в базе данных есть таблица, и 2) участники не выходят из строя, но, похоже, в ней нет элементов:

5. var result2 = db.Участники; <— НЕ ПРИВОДИТ К СБОЮ var result3 = db.Участники. Где (xyz => xyz.Id == 1). ToList(); <— СБОЙ С ОШИБКОЙ

Ответ №1:

Я добавляю db.Database.EnsureCreated(); перед обновлением данных:

 public MainPage()
{
    InitializeComponent();

    //iOS
    var dbPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "..", "Library", "iOSTest.db");

    // Android
    var dbPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), "AndroidTest.db");



    // Create Database amp; Tables
    using (var db = new DatabaseContext(dbPath))
    {

        db.Database.EnsureCreated();

        // Insert Data
        db.Add(new Participant() { Fname = "time: "   DateTime.Now.ToString() });
        db.SaveChanges();

        // Retrieve Data
        // Next two lines receive error in scenario 2
        var result2 = db.Participants.Where(xyz => xyz.Id == 1).ToList();
        IEnumerable<Participant> p = db.Participants.ToList();
    }
}
  

И контекст БД:

   // DB Context

    public class DatabaseContext : DbContext
    {
        string _dbPath;

        public DbSet<Participant> Participants { get; set; }

        public DatabaseContext(string dbPath)
        {
            _dbPath = dbPath;

        }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlite($"Filename={_dbPath}");
        }
    }
  

1. Вы можете попробовать изменить имя базы данных в своем проекте, чтобы проверить, есть ли какие-либо неправильные данные в старой базе данных.
2. Проблемы могут быть вызваны асинхронным методом.

Комментарии:

1. Спасибо за ваш ответ. Я попытался добавить «db.Database. EnsureCreated();» строка непосредственно перед строками «db.Add …», но получил ту же ошибку. То же самое произошло, когда я только что вызвал метод ensurecreated в файле DbContext. Все работает только тогда, когда я УДАЛЯЮ (ensuredeleted) в том же прогоне, что и ensurecreated, добавляю данные, а затем извлекаю их в том же прогоне.

2. @Donna Итак, проблема в том, что у участников нет элемента. Поскольку вы можете извлекать базу данных и просматривать данные, можете ли вы видеть данные в таблице с Id = 1? Используете ли вы тот же код, что и мой, какой-либо дополнительный код? Вы можете создать новый проект и использовать мой код, он работает на моей стороне. И вы дали своей базе данных новое имя для тестирования?

Ответ №2:

Проблема решена! Оказалось, что это DbContext и как / где это было определено против где его пытались использовать. Код был реструктурирован, чтобы не потерять область контекста перед выполнением операций чтения и записи.