#c# #sqlite #xamarin #xamarin.forms #many-to-many
#c# #sqlite #xamarin #xamarin.forms #многие ко многим
Вопрос:
У меня есть четыре таблицы со свойствами (член, в котором есть игроки, и каждый из них участвует во многих видах спорта), последняя таблица — промежуточная таблица для отношений «многие ко многим»
[Table("Members")]
public class MemberModel : BaseDatabaseItem
{
public string MemberShipCode { get; set; }
public string MemberShipYear { get; set; }
[OneToMany(CascadeOperations = CascadeOperation.All)]
public List<PlayerModel> MembershipNPlayers { get; set; }
}
[Table("Players")]
public class PlayerModel : BaseDatabaseItem
{
public string PlayerName { get; set; }
public double PlayerPayment { get; set; }
[ForeignKey(typeof(MemberModel))]
public int MemberModelId { get; set; }
[ManyToMany(typeof(PlayerSport))]
public List<Sport> Sports { get; set; }
}
[Table("Sports")]
public class Sport : BaseDatabaseItem
{
private SportCaegory sportCaegory;
public string SportName { get; set; }
[Ignore]
public SportCaegory SportCaegory
{
get
{
return sportCaegory = new SportCaegory
{
SportPrice = SportPrice,
SportType = SportType
};
}
set
{
sportCaegory = value;
if (sportCaegory == null)
return;
SportType = sportCaegory.SportType;
SportPrice = sportCaegory.SportPrice;
}
}
public string SportType { get; set; }
public double SportPrice { get; set; }
[ManyToMany(typeof(PlayerSport))]
public List<PlayerModel> Players { get; set; }
}
public class PlayerSport : BaseDatabaseItem
{
[ForeignKey(typeof(PlayerModel))]
public int PlayerModelId { get; set; }
[ForeignKey(typeof(Sport))]
public int SportId { get; set; }
}
BaseDataItem — это только класс, у которого есть идентификатор (первичный — AutoIn)
Когда я сохраняю участника в базе данных, я сохраняю спортивные состязания, затем игроков и, наконец, участника
foreach (var sport in Players.SelectMany(p => p.Sports))
{
await _sportsRepository.SaveItemAsync(new Sport
{
Id = sport.Id == 0 ? 0 : sport.Id,
SportName = sport.SportName,
SportCaegory = sport.SportCaegory
});
};
foreach (var player in Players)
{
await _playersRepository.SaveItemAsync(new PlayerModel
{
Id = player.Id == 0 ? 0 : player.Id,
PlayerName = player.PlayerName,
PlayerPayment = player.PlayerPayment,
Sports = player.Sports
});
await _playersRepository.SaveWithChildrenAsync(player);
};
var member = new MemberModel
{
Id = string.IsNullOrEmpty(Id) ? 0 : int.Parse(Id),
MemberShipCode = MemberShipCode,
MemberShipYear = MemberShipYear,
MembershipNPlayers = Players.ToList()
};
await _membersRepository.SaveWithChildrenAsync(member);
SaveWithChildrenAsync (только проверка идентификаторов) =>
public async Task SaveWithChildrenAsync(T entity)
{
if (entity.Id != 0)
await UpdateWithChildren(entity);
else
await InsertWithChildren(entity);
}
При повторном просмотре данных количество спортивных списков всегда равно нулю для каждого игрока
var member = await _membersRepository.GetWithChildren(MemberId) ;
var MemberPlayers = member.MembershipNPlayers;
foreach (var player in MemberPlayers)
{
var p = await _playersRepository.GetWithChildren(player.Id);
Players.Add(p);
}
MemberShipCode = member.MemberShipCode;
MemberShipYear = member.MemberShipYear;
Как это решить?
Ответ №1:
Из-за некоторых частей кода, которые вы не предоставили, я создаю простой код для обновления базы данных и получения данных. Вы можете проверить приведенный ниже код.
Классы модели:
[Table("Members")]
public class MemberModel : BaseDatabaseItem
{
public string MemberShipCode { get; set; }
public string MemberShipYear { get; set; }
[OneToMany(CascadeOperations = CascadeOperation.All)]
public List<PlayerModel> MembershipNPlayers { get; set; }
}
public class BaseDatabaseItem
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
}
[Table("Players")]
public class PlayerModel : BaseDatabaseItem
{
public string PlayerName { get; set; }
public double PlayerPayment { get; set; }
[ForeignKey(typeof(MemberModel))]
public int MemberModelId { get; set; }
[ManyToMany(typeof(PlayerSport))]
public List<Sport> Sports { get; set; }
}
[Table("Sports")]
public class Sport : BaseDatabaseItem
{
private SportCaegory sportCaegory;
public string SportName { get; set; }
[Ignore]
public SportCaegory SportCaegory
{
get
{
return sportCaegory = new SportCaegory
{
SportPrice = SportPrice,
SportType = SportType
};
}
set
{
sportCaegory = value;
if (sportCaegory == null)
return;
SportType = sportCaegory.SportType;
SportPrice = sportCaegory.SportPrice;
}
}
public string SportType { get; set; }
public double SportPrice { get; set; }
[ManyToMany(typeof(PlayerSport))]
public List<PlayerModel> Players { get; set; }
}
public class SportCaegory
{
public string SportType { get; set; }
public double SportPrice { get; set; }
}
public class PlayerSport : BaseDatabaseItem
{
[ForeignKey(typeof(PlayerModel))]
public int PlayerModelId { get; set; }
[ForeignKey(typeof(Sport))]
public int SportId { get; set; }
}
Вставка и чтение данных:
var dbName = "CustomersDb.db3";
var path = Path.Combine(System.Environment.
GetFolderPath(System.Environment.
SpecialFolder.Personal), dbName);
var db = new SQLiteConnection(path);
db.CreateTable<MemberModel>();
db.CreateTable<PlayerModel>();
db.CreateTable<PlayerSport>();
db.CreateTable<Sport>();
var Member1 = new MemberModel()
{
MemberShipCode = "A",
MemberShipYear = "111"
};
var Player1 = new PlayerModel()
{
MemberModelId = 12,
PlayerName = "B",
PlayerPayment = 1.2,
};
var SportPlayer1 = new PlayerSport()
{
PlayerModelId = 1,
SportId = 2
};
var Sport1 = new Sport()
{
SportCaegory = new SportCaegory()
{
SportPrice = 12,
SportType = "tY"
},
SportName = "Name1",
SportPrice = 13,
SportType = "ww"
};
db.Insert(Member1);
db.Insert(Player1);
db.Insert(Sport1);
db.Insert(SportPlayer1);
Member1.MembershipNPlayers = new List<PlayerModel> { Player1 };
Player1.Sports = new List<Sport> { Sport1 };
Sport1.Players = new List<PlayerModel>() { Player1 };
db.UpdateWithChildren(Member1);
db.UpdateWithChildren(Sport1);
db.UpdateWithChildren(Player1);
var M = db.GetWithChildren<MemberModel>(Member1.Id);
var P = db.GetWithChildren<PlayerModel>(Player1.Id);
Скриншот:
Комментарии:
1. Являются ли идентификаторы в SportPlayer1 случайными и будут перезаписаны, если нет, как вы вставляете хранилище?
2. Идентификаторы SportPlayer1 унаследованы от
BaseDatabaseItem
. ИдентификаторBaseDatabaseItem
— это PrimaryKey и АвтоИнкремент. Это приведет к автоматическому увеличению значения целочисленного свойства для каждого нового объекта, вставляемого в базу данных. Оно не будет перезаписано вместо вставки с существующим идентификатором.3. Не первичные ключи, а дочерние внешние ключи, но, благодаря, я не вставлял sports в базу данных, поэтому он всегда нулевой