Как создать отношения с SQLite (внешний ключ)

#c# #xamarin #xamarin.forms #sqlite

#c# #xamarin #xamarin.forms #sqlite

Вопрос:

Я пытаюсь создать отношения со своими таблицами в SQLite (в настоящее время я работаю с Xamarin.Формы), но я не получаю ожидаемого результата, добавляя аннотации к данным [ForeignKey(typeof(UserLocal))] , но я не создаю отношения в своем BD, что происходит? мой BD выполняет только индексированные отношения, но не связывает их с внешними ключами

Браузер SQLite

Для подключения к моей базе данных я создал интерфейс, который получает маршрут в Android и iOS, а затем для управления моей ВСТАВКОЙ, ОБНОВЛЕНИЕМ, УДАЛЕНИЕМ и т. Д… Я делаю это из службы данных.Служба CS.

Android:

 [assembly: Xamarin.Forms.Dependency(typeof(PathService))]
namespace AppValora.Droid.Implementation
{
    public class PathService : IPathService
    {
        public string GetDatabasePath()
        {              
            string path = Android.OS.Environment.ExternalStorageDirectory.AbsolutePath;
            var directoryPath = Path.Combine(path, "Valora/Databases");
            if (!Directory.Exists(directoryPath))
            {
                try
                {

                    Directory.CreateDirectory(directoryPath);
                }
                catch (Exception ex)
                {

                }
            }
            return Path.Combine(directoryPath, "Valora.db3");
        }
    }
}
  

iOS:

 [assembly: Dependency(typeof(PathService))]
namespace AppValora.iOS.Implementation
{
    public class PathService : IPathService
    {
        public string GetDatabasePath()
        {
            string docFolder = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
            string libFolder = Path.Combine(docFolder, "..", "Library");

            if (!Directory.Exists(libFolder))
            {
                Directory.CreateDirectory(libFolder);
            }

            return Path.Combine(libFolder, "Valora.db3");
        }
    }
}
  

DATASERVICE.CS:

 #region Servicios
private SQLiteAsyncConnection connection;
private DialogService dialogService;       
#endregion

#region Constructor
public DataService()
{
    dialogService = new DialogService();
    OpenOrCreateDB();
}
#endregion

private async Task OpenOrCreateDB()
{
    var status = await CrossPermissions.Current.CheckPermissionStatusAsync(Plugin.Permissions.Abstractions.Permission.Storage);

    if (status != Plugin.Permissions.Abstractions.PermissionStatus.Granted)
    {
        if (await CrossPermissions.Current.ShouldShowRequestPermissionRationaleAsync((Plugin.Permissions.Abstractions.Permission.Storage)))
        {
            await dialogService.ShowMessage("!ATENCIÓN!", "Valora necesita el permiso de archivos para este proceso.");
        }

        var results = await CrossPermissions.Current.RequestPermissionsAsync((Plugin.Permissions.Abstractions.Permission.Storage));
        //Best practice to always check that the key exists
        if (results.ContainsKey(Plugin.Permissions.Abstractions.Permission.Storage))
            status = results[Plugin.Permissions.Abstractions.Permission.Storage];
    }

    if (status == Plugin.Permissions.Abstractions.PermissionStatus.Granted)
    {
        //CONSULTO PATH
        var databasePath = DependencyService.Get<IPathService>().GetDatabasePath();
        //CREO LA CONEXION
        this.connection = new SQLiteAsyncConnection(databasePath);
        //CREACION DE TABLAS
        await connection.CreateTableAsync<UserLocal>().ConfigureAwait(false);
        await connection.CreateTableAsync<Companie>().ConfigureAwait(false);
    }
    else if (status != Plugin.Permissions.Abstractions.PermissionStatus.Unknown)
    {

    }    

    public async Task Insert<T>(T model)
    {
        await this.connection.InsertAsync(model);
    }
}
  

The DataService in addition to making the connection creates the tables in which I want to generate the relationship, The data model are the following…

USERLOCAL.CS:

 public class UserLocal
{
    [PrimaryKey, AutoIncrement]
    public int Id { get; set; }

    public int IdLogin { get; set; }
    public string Token { get; set; }             
    public string Nombre { get; set; }
    public string Rut { get; set; }
    public bool Recordado { get; set; }
    public string Password { get; set; }

    [OneToMany]
    public List<Companie> Companies { get; set; }
}
  

COMPANIE.CS:

 public class Companie
{
    [PrimaryKey, AutoIncrement]
    public int Id { get; set; }

    public int IdLogin { get; set; }
    public string Nombre { get; set; }
    public bool Principal { get; set; }
    public bool ExternalCorp { get; set; }
    public bool IsCorporate { get; set; }

    [ForeignKey(typeof(UserLocal))]
    public int IdUser { get; set; }

    [ManyToOne]
    public UserLocal UserLocal { get; set; }
}
  

Далее, ниже показан код вставки записей в мои таблицы, я думаю, что именно в этой части я ошибаюсь, поскольку я не могу создать отношения

VIEWMODEL.CS:

 ListaCompanie.Clear();          

// I WALK THE NUMBER OF COMPANIES THAT I WANT TO ADD
foreach (var item in loginResponse.Companies)
{
    var companie = new Companie
    {
        IdLogin = item.Id,
        Nombre = item.Name,
        ExternalCorp = item.ExternalCorp,
        IsCorporate = item.IsCorporate,
        Principal = item.Principal,
        //CLAVE FORANEA
        IdUser = loginResponse.Id,
    };

    ListaCompanie.Add(companie);

    await dataService.Insert(companie);
}

var user = new UserLocal
{
        IdLogin = loginResponse.Id,
        Nombre = loginResponse.Name,
        Recordado = Settings.Recordado,
        Rut = loginResponse.Rut,
        Token = loginResponse.Token,
        Password = GetSHA1(Settings.Password),
        Companies = ListaCompanie,
};

await dataService.Insert(user);
  

Почему эти отношения не создаются? Как я могу связать свои таблицы с SQLite? что я делаю не так? Я работаю с Xamarin.Формы с архитектурным шаблоном MVVM, любая помощь для меня?

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

1. Как я могу проверить, хотите ли вы достичь этого с помощью кода в первую очередь, это правда?

2. да, sr! @Avinash

3. Вы удалили свой последний вопрос, прежде чем я смог нажать «Опубликовать ответ». : (

4. Мой ответ на этот вопрос здесь , если вам интересно.

Ответ №1:

Если вы используете SQLite.Net.Extensions для создания отношений, вам нужно установить CascadeOperations подобное:

 public class UserLocal
{
    [PrimaryKey, AutoIncrement]
    public int Id { get; set; }
    public int IdLogin { get; set; }
    public string Token { get; set; }             
    public string Nombre { get; set; }
    public string Rut { get; set; }
    public bool Recordado { get; set; }
    public string Password { get; set; }

    // THIS BIT HERE 
    [OneToMany(CascadeOperations = CascadeOperation.All)]
    public List<Companie> Companies { get; set; }
}
  

Другое дело, если вы используете эту библиотеку, тогда вы можете insertWithChildren создать отношения следующим образом:

 var user = new UserLocal
{
    IdLogin = loginResponse.Id,
    Nombre = loginResponse.Name,
    Recordado = Settings.Recordado,
    Rut = loginResponse.Rut,
    Token = loginResponse.Token,
    Password = GetSHA1(Settings.Password),
    Companies = ListaCompanie,
};

// I WALK THE NUMBER OF COMPANIES THAT I WANT TO ADD
foreach (var item in loginResponse.Companies)
{
    var companie = new Companie
    {
        IdLogin = item.Id,
        Nombre = item.Name,
        ExternalCorp = item.ExternalCorp,
        IsCorporate = item.IsCorporate,
        Principal = item.Principal,
        //CLAVE FORANEA
        UserLocal = user,
        // You dont need to set this as it will be assigned in InsertWithChildren
        // IdUser = loginResponse.Id,
    };

    ListaCompanie.Add(companie);

    await dataService.InsertWithChildren(companie);
}
  

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

1. Ваше объяснение кажется логичным и уместным, но при вызове метода Insert with children в моей службе данных он не может быть вызван, как я могу его создать? IntelliSense ничего мне не предлагает, какое-либо дополнение к вашему ответу?

2. InsertWithChildren является частью Sqlite.net.Extensions. Подробнее об этом можно прочитать здесь bitbucket.org/twincoders/sqlite-net-extensions/overview . Если вы используете его, вам нужно будет добавить using using SQLiteNetExtensions.Extensions; или using SQLiteNetExtensionsAsync.Extensions;

3. Ваш ответ: я заполняю только таблицу Companie и с ее внешним ключом (idUser = 0), таблица UserLocal не заполняет ее… какие-либо рекомендации по одобрению вашего ответа? @Ян Смит