问题
I'm trying to create relationships with my tables in SQLite (I'm currently working with Xamarin.Forms), but I'm not getting the expected result, adding the Data Annotations [ForeignKey(typeof(UserLocal))]
But I'm not creating the relationship in my BD, what's going on? my BD is only doing the indexed relationships, but it is not relating them to foreign keys
Browser SQLite
For the connection to my database, I created an interface which gets the route in Android and iOS, and then to manage my INSERT, UPDATE, DELETE, etc ... I do it from the DataService.CS service.
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; }
}
Next, the code of how to insert the records in my tables is shown below, I think it is in this part where I am wrong, since I am not able to create the relationships
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);
Why are these relationships not generated? How can I relate my tables to SQLite? what am I doing wrong? I am working with Xamarin.Forms with an MVVM architectural pattern, any help for me?
回答1:
If you are using SQLite.Net.Extensions for creating the relationships then you need to set the CascadeOperations
like so:
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; }
}
The other thing is if you are using this library then you can insertWithChildren
to create the relationship like so:
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);
}
来源:https://stackoverflow.com/questions/55573511/how-to-create-relationships-with-sqlite-foreign-key