2014-10-06 24 views
6

Ben şu entites/tablolar:WP8 & Linq Bire Bir çok ilişki ile SQL: kaldırır) (SubmitChanges yanlış varlık

  • Board: Tek tahta sahip olabilecek birçok pimleri
  • Pin: Tek pin bir tahtaya atanır. Bu varlık soyut ve farklı uygulamalarla çocuk sahibi. Bütün oğul InheritanceMapping ile ana pimi varlığa ait bir Discriminator column
    • TaskPin tarafından pim masa ve seçkin içine kaydedilecektir: Bu pimin bir çocuk uygulamaları olduğunu. Pek çok görevi olabilir.
  • Task: Tek görev benim yapısını daha net hale getirmek için Buraya

TaskPin birine bazı kod olduğu atanır:

[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() 
    { 

    } 
} 

Ben TaskPin oluşturmak ve bir tahta atayın. Sonra iki görev oluşturup bunları TaskPin'e atayım. Bu iyi çalışıyor.

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); 
     } 
    } 

benim DataContext nesne üzerinde daha sonra SubmitChanges() ararsanız

, bu null için (Pin miras) TaskPin ait Board property ayarlayacaktır: Ben TaskPin den birine veya birkaçına Tasks çalıştığınızda sorun occurrs.

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(); 
    } 

Ben DeleteOnNull true olarak ayarlanır çünkü Task silineceğini bekliyoruz ama Pin Board property ayrıca NullPointerExceptio veya Pim de silinir olduğunu sonuçlanacaktır null ayarlandığında neden bilmiyorum .

Bu konuyla ilgili bir google araması yaptım ancak sorunumu çözen hiçbir şey bulamadım. Bir Alternatif, Yönetim Kurulu mülkünün iptal edilmesini önlemek ve Görev için manuel olarak DeleteOnSubmit()'u aramak olacaktır.

+0

Datacontext'i nasıl kullanıyorsunuz - her defasında bir kez oluşturun veya yeniden oluşturun? Sql profiler ile tanıyor musunuz? İki işleminiz var ve profiler ile izleyici olabilirim. –

+0

'changeSet'iniz' Board' için null olmayan bir referans içeriyor mu? Nesne grafiğinizin diğer faktörlerden dolayı yüklenmediğinden şüpheleniyorum. – Mrchief

+0

@Mrchief nesne grafiğinde ne demek istiyorsun? ChangeSet, TaskPin'in silinmesi için bir giriş içerir. –

cevap

0

Benim için davranışın amaçlandığı anlaşılıyor. Eğer Görev sınıfında Pim mülkiyet bakarsak

, Null sonra Görev yılında Pimuyarınca silinecek (DeleteOnNull = true) silinecek ayarlandığında removeTask() TaskPin sınıfında sınıfı.Sonra null Pin ait Kurulu setleri Kurulu sınıfında removePin() yöntemine bakın. Sonra Pim sınıfında Kurulu özelliği bakmak, DeleteOnNull null ayarlandığında Pim örneğinden Kurulu silecektir hangi true olarak ayarlanır.