#c# #xamarin #xamarin.forms #sqlite
#c# #xamarin #xamarin.forms #sqlite
Вопрос:
Я пытаюсь создать отношения со своими таблицами в SQLite (в настоящее время я работаю с Xamarin.Формы), но я не получаю ожидаемого результата, добавляя аннотации к данным [ForeignKey(typeof(UserLocal))]
, но я не создаю отношения в своем BD, что происходит? мой BD выполняет только индексированные отношения, но не связывает их с внешними ключами
Для подключения к моей базе данных я создал интерфейс, который получает маршрут в 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 . Если вы используете его, вам нужно будет добавить usingusing SQLiteNetExtensions.Extensions;
илиusing SQLiteNetExtensionsAsync.Extensions;
3. Ваш ответ: я заполняю только таблицу Companie и с ее внешним ключом (idUser = 0), таблица UserLocal не заполняет ее… какие-либо рекомендации по одобрению вашего ответа? @Ян Смит