2015-03-18 6 views
0

Я использую SQLite-Net PCL вместе с расширениями SQLite-Net для разработки приложения с использованием Xamarin.Проблема с расширением SQLite.Net с InsertOrReplaceWithChildren

У меня есть два класса A и B определены следующим образом:

public class A 
{ 

    [PrimaryKey, AutoIncrement] 
    public int Id 
    { 
     get; 
     set; 
    } 

    [Unique] 
    public string Name 
    { 
     get; 
     set; 
    } 

    [OneToMany(CascadeOperations = CascadeOperation.All)] 
    public List<B> Sons 
    { 
     get; 
     set; 
    } 

    public A(string name, List<B> sons) 
    { 
     Name = name; 
     Sons = sons; 
    } 

} 

public class B 
{ 

    [PrimaryKey, AutoIncrement] 
    public int Id 
    { 
     get; 
     set; 
    } 

    [Unique] 
    public string Name 
    { 
     get; 
     set; 
    } 

    public string LastModified 
    { 
     get; 
     set; 
    } 

    [ForeignKey(typeof(A))] 
    public int FatherId 
    { 
     get; 
     set; 
    } 

    [ManyToOne] 
    public A Father 
    { 
     get; 
     set; 
    } 

    public B() 
    { 
    } 

    public B(string name) 
    { 
     Name = name; 
    } 

} 

Я пытаюсь использовать вставку или заменить следующим образом:

 var sons1 = new List<B> 
     { 
      new B("uno"), 
     }; 

     var a1 = new A("padre", sons1); 

     var sons2 = new List<B> 
     { 
      new B("uno2"), 
     }; 

     var a2 = new A("padre", sons2); 

     using (var conn = DatabaseStore.GetConnection()) 
     { 
      conn.DeleteAll<A>(); 
      conn.DeleteAll<B>(); 
     } 

     using (var conn = DatabaseStore.GetConnection()) 
     { 
      conn.InsertOrReplaceWithChildren(a1, true); 
      conn.InsertOrReplaceWithChildren(a2, true); 
     } 

Проблема заключается в том, что второй InsertOrReplaceWithChildren является бросая исключение Constraint, которое не выбрасывается, если мы удалим уникальное ограничение на A.Name. Разве InsertOrReplaceWithChildren должен заменить объект, если нарушено уникальное ограничение?

+0

Звучит как ошибка. Возможно, здесь: https://bitbucket.org/twincoders/sqlite-net-extensions/src/fe7c6539bf56f652aae06d0af26b54cff2ffcfd3/SQLiteNetExtensions/Extensions/WriteOperations.cs?at=master#cl-272 – redent84

ответ

1

Я проверил фиксации для этой строки, теперь я помню: кажется, что первичный ключ AutoIncrement работает только для Insert, а не для InsertOrReplace. Как следствие, если вы вызываете InsertOrReplace с первичным ключом AutoIncrement, установленным в 0, он всегда будет перезаписывать одно и то же значение в базе данных с идентификатором 0 вместо правильного добавления новых значений.

Этот вопрос легко проверить, выполнив этот тест:

var a = new List<A> { 
    new A("a1", null), 
    new A("a2", null), 
    new A("a3", null), 
    new A("a4", null), 
    new A("a5", null), 
    new A("a6", null) 
}; 

foreach (var element in a) { 
    conn.InsertOrReplace(element); 
} 

// Will fail expecting 6 elements but returning only 1 
Assert.AreEqual(a.Count, conn.Table<A>().ToList().Count); 

Чтобы решить эту проблему, вы должны отказаться либо первичный ключ AutoIncrement или проверку Unique ограничений для InsertOrReplace заявление на работу.

Это капля в классах замены, которые должны работать, как ожидаются отказ от AutoIncrement первичных ключей:

public class A 
{ 

    [PrimaryKey] 
    public Guid Id { get; set; } 

    [Unique] 
    public string Name { get; set; } 

    [OneToMany(CascadeOperations = CascadeOperation.All)] 
    public List<B> Sons { get; set; } 

    public A() {} 
    public A(string name, List<B> sons) 
    { 
     Id = Guid.NewGuid(); 
     Name = name; 
     Sons = sons; 
    } 
} 

public class B 
{ 

    [PrimaryKey] 
    public Guid Id { get; set; } 

    [Unique] 
    public string Name { get; set; } 

    public string LastModified { get; set; } 

    [ForeignKey(typeof(A))] 
    public Guid FatherId { get; set; } 

    [ManyToOne] 
    public A Father { get; set; } 

    public B() {} 

    public B(string name) 
    { 
     Id = Guid.NewGuid(); 
     Name = name; 
    } 
} 

Надеется, что это помогает.

+0

Спасибо за помощь. На самом деле я работаю над моделью данных, которая сложнее, чем эта, поэтому каждый раз, когда я вставляю, я проверяю, есть ли объект уже там. Честно говоря, у меня была еще одна странная проблема, к сожалению, мне не удалось воспроизвести ее с меньшим примером, но я нашел обходное решение для этого. – markusian

+0

Кроме того, я считаю, что источником путаницы также является тот факт, что ваш пример будет работать с 'InsertOrReplaceWithChildren' и он правильно назначит идентификаторы – markusian

Смежные вопросы