WP8 and Linq to SQL with a one-to-many relationship: SubmitChanges () removes the wrong object

I have the following enites / tables:

  • Board : there can be many pins on one board
  • Pin : One pin is assigned to one board. This object is abstract and has children with various implementations. All children belonging to the parent contact with InheritanceMapping will be saved in the contact table and highlighted with the Discriminator column
    • TaskPin : This is one TaskPin implementation of pin. It can have many tasks.
  • Task : one task is assigned to one TaskPin

Here is the code to make my structure more understandable:

 [Table] public class Board : ModelBase { private int _boardId; [Column(IsPrimaryKey = true, IsDbGenerated = true, DbType = "INT NOT NULL Identity" ,CanBeNull = false, AutoSync = AutoSync.OnInsert)] public int BoardId { get { return _boardId; } set { SetProperty(ref _boardId, value); } } private EntitySet<Pin> _pins; [Association(Storage = "_pins", OtherKey = "_boardId" ,ThisKey = "BoardId", DeleteRule = "CASCADE")] public EntitySet<Pin> Pins { get { return _pins; } set { _pins.Assign(value); } } public Board() { _pins = new EntitySet<Pin>(new Action<Pin>(this.addPin) ,new Action<Pin>(this.removePin)); } private void addPin(Pin pin) { NotifyPropertyChanging("Pin"); pin.Board = this; } private void removePin(Pin pin) { NotifyPropertyChanging("Pin"); pin.Board = null; } } 

 [Table] [InheritanceMapping(Code = PinType.TaskPin, Type = typeof(TaskPin) ,IsDefault = true)] public abstract class Pin : ModelBase { private int _pinId; [Column(IsPrimaryKey = true, IsDbGenerated = true ,DbType = "INT NOT NULL Identity", AutoSync = AutoSync.OnInsert)] public int PinId { get { return _pinId; } set { SetProperty(ref _pinId, value); } } [Column] internal int _boardId; private EntityRef<Board> _board; [Association(Storage = "_board", ThisKey = "_boardId" ,OtherKey = "BoardId", IsForeignKey = true, DeleteOnNull = true)] public Board Board { get { return _board.Entity; } set { if (SetProperty(ref _board, value) != null) { _boardId = value.BoardId; } } } [Column(IsDiscriminator = true)] public PinType Type { get; set; } public Pin() { } } 

 public class TaskPin : Pin { private EntitySet<Task> _tasks; [Association(Storage = "_tasks", OtherKey = "_pinId" ,ThisKey = "PinId", DeleteRule = "CASCADE")] public EntitySet<Task> Tasks { get { return _tasks; } set { _tasks.Assign(value); } } public TaskPin() { _tasks = new EntitySet<Task>(new Action<Task>(this.addTask) ,new Action<Task>(this.removeTask)); } private void addTask(Task task) { NotifyPropertyChanging("Task"); task.Pin = this; } private void removeTask(Task task) { NotifyPropertyChanging("Task"); task.Pin = null; } } 

 [Table] public class Task : ModelBase { private int _taskId; [Column(IsPrimaryKey = true, IsDbGenerated = true ,DbType = "INT NOT NULL Identity" ,CanBeNull = false, AutoSync = AutoSync.OnInsert)] public int TaskId { get { return _taskId; } set { SetProperty(ref _taskId, value); } } [Column] internal int _pinId; private EntityRef<Pin> _pin; [Association(Storage = "_pin", ThisKey = "_pinId" ,OtherKey = "PinId" ,IsForeignKey = true ,DeleteOnNull=true)] public Pin Pin { get { return _pin.Entity; } set { if (SetProperty(ref _pin, value) != null) { _pinId = value.PinId; } } } public Task() { } } 

I create TaskPin and assign it to the board. Then I create two tasks and assign them TaskPin. This works great. The problem occurs when I try to execute one or more Tasks from TaskPin :

  private void OnDeleteTasks(object sender, EventArgs e) { TaskPin taskPin = pin as TaskPin; var completedTasks = taskPin.Tasks .Where(x => x.IsDone == true) .ToList(); foreach (var task in completedTasks) { taskPin.Tasks.Remove(task); } } 

If I call SubmitChanges() on my DataContext , it will set the Board property TaskPin (inherited from Pin) to null .

  public void Save(Pin pin) { // This is empty so no modified members are identified => Correct var modifiedMembers = db.Pins.GetModifiedMembers(pin); // Contains just one entry for the deleted Task entity => Correct var changeSet = db.GetChangeSet(); // This call will immediately set Board property of Pin to null => Wrong! db.SubmitChanges(); } 

I expect Task be deleted because the DeleteOnNull parameter is set to true, but I don't know why the Board property for Pin is also set to null , which will result in a NullPointerExceptio or that the Pin is also deleted.

I did a search on this topic on Google, but I did not find anything that would solve my problem. An alternative would be to prevent the Board property from being reset and calling DeleteOnSubmit() manually for the task.

+6
source share
1 answer

It seems to me that the behavior is intended.

If you look at the Pin property in the Task class, it will be deleted in Null ( DeleteOnNull = true ), which then the Pin in the Task will be deleted in accordance with removeTask () in the TaskPin class. Then, look at the removePin () method in the Tip class, which sets the Pin Tip to null. Then look at the Tip property in the Pin class, DeleteOnNull is set to true, which will remove the Tip from Pin when null is set.

0
source

Source: https://habr.com/ru/post/976325/


All Articles