#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 и как / где это было определено против где его пытались использовать. Код был реструктурирован, чтобы не потерять область контекста перед выполнением операций чтения и записи.