0

I would like to do the simplest thing - fetch data from db. When I make a query and later call SubmitChanges() on DataContext object, all the fetched items are deleted from DB. Here's the code:

SubmitChanges(); // nothing happened (it is OK)
List<Flashcard> list = (from f in FlashcardsTable
                        where f.Category.IsSelected
                              && !excluded.Contains(f.FlashcardId)
                        select f).ToList();
SubmitChanges(); // All items from list are deleting from DB!!

FlashcardsTable is a table in DB, excluded is just a list with integers.

My question is why data from DB is deleted when SubmitChanges() is called and how to fix it (I want to leave the data in the database).


I'm still searching answer for my questions... Here are more details from my code, maybe it helps?

I do 2 things in my app. First create 100 items and put them to DB:

var db = new DbContext();
var flashcard = new Flashcard();
// here sets some fields on flashcard, not important...
for (var i = 0; i < 100; i++)
{
    var cat = db.CategoriesTable.First(c => c.CategoryId == categoryId);
    cat.Count++;
    flashcard.Category = cat;
    flashcard.BasketNr = 1;
    flashcard.TimeToCheck = Utils.CurrentDate.AddHours(12);
    db.FlashcardsTable.InsertOnSubmit(new Flashcard(flashcard));
}
db.SubmitChanges();

Next I make a query on DB:

var db = new DbContext();
db.SubmitChanges(); // here is OK, no SQL was generated
var a = (from f in db.FlashcardsTable
         where f.Category.IsSelected
         select f).ToList();
db.SubmitChanges(); // here are generated 100 SQLs deleting my data

After call second db.SubmitChanges() are generated 100 SQLs like:

DELETE FROM [Flashcard] WHERE [FlashcardId] = @p0

-- @p0: Input Int32 (Size = 4; Prec = 0; Scale = 0) [1]

-- Context: SqlProvider(SqlCE) Model: AttributedMetaModel Build: System.Data.Linq, Version=7.0.0.0, Culture=neutral, PublicKeyToken=24EEC0D8C86CDA1E

Maybe definitions of Tables are wrong? Here it is:

[Table]
public class Category : INotifyPropertyChanged {

    public event PropertyChangedEventHandler PropertyChanged;

    private string name;
    [Column(IsPrimaryKey = true, IsDbGenerated = true, DbType = "INT NOT NULL Identity", CanBeNull = false, AutoSync = AutoSync.OnInsert)]
    public int CategoryId { get; set; }

    [Column(UpdateCheck = UpdateCheck.Never)]
    public string Name {
        get { return name; }
        set {
            if (name != value) {
                name = value;
                if (PropertyChanged != null) {
                    PropertyChanged(this, new PropertyChangedEventArgs("Name"));
                }
            }
        }
    }

    [Column(UpdateCheck = UpdateCheck.Never)]
    public int Count { get; set; }

    [Column(UpdateCheck = UpdateCheck.Never)]
    public bool IsSelected { get; set; }

}



[Table]
public class Flashcard {
    public const int TYPE_TEXT = 1;
    public const int TYPE_BITMAP = 2;

    [Column(IsPrimaryKey = true, IsDbGenerated = true, DbType = "INT NOT NULL Identity", CanBeNull = false, AutoSync = AutoSync.OnInsert)]
    public int FlashcardId { get; set; }

    [Column(UpdateCheck = UpdateCheck.Never)]
    public DateTime TimeToCheck { get; set; }

    [Column(CanBeNull = false, UpdateCheck = UpdateCheck.Never)]
    public int Type { get; set; }

    private byte[] firstPageBitmap;
    private byte[] secondPageBitmap;
    private string firstPageText;
    private string secondPageText;

    public Flashcard(Flashcard flashcard) {
        FirstPageBitmap = flashcard.FirstPageBitmap;
        SecondPageBitmap = flashcard.SecondPageBitmap;
        FirstPageType = flashcard.FirstPageType;
        SecondPageType = flashcard.SecondPageType;
        BasketNr = flashcard.BasketNr;
        Category = flashcard.Category;
        TimeToCheck = flashcard.TimeToCheck;
    }

    public Flashcard() {
    }

    [Column(DbType = "image", UpdateCheck = UpdateCheck.Never, CanBeNull = true)]
    public byte[] FirstPageBitmap {
        get { return firstPageBitmap; }
        set {
            FirstPageType = TYPE_BITMAP;
            firstPageBitmap = value;
        }
    }

    [Column(CanBeNull = true, UpdateCheck = UpdateCheck.Never)]
    public string FirstPageText {
        get { return firstPageText; }
        set {
            FirstPageType = TYPE_TEXT;
            firstPageText = value;
        }
    }

    [Column(UpdateCheck = UpdateCheck.Never)]
    public int FirstPageType { get; set; }

    [Column(UpdateCheck = UpdateCheck.Never)]
    public int SecondPageType { get; set; }

    [Column(DbType = "image", UpdateCheck = UpdateCheck.Never, CanBeNull = true)]
    public byte[] SecondPageBitmap {
        get { return secondPageBitmap; }
        set {
            SecondPageType = TYPE_BITMAP;
            secondPageBitmap = value;
        }
    }

    [Column(CanBeNull = true, UpdateCheck = UpdateCheck.Never)]
    public string SecondPageText {
        get { return secondPageText; }
        set {
            SecondPageType = TYPE_TEXT;
            secondPageText = value;
        }
    }

    [Column(UpdateCheck = UpdateCheck.Never)]
    public int BasketNr { get; set; }

    [Column(UpdateCheck = UpdateCheck.Never)]
    public int CatId { get; set; }

    [Association(ThisKey = "CatId", OtherKey = "CategoryId", IsForeignKey = true, DeleteOnNull = true)]
    public Category Category { get; set; }
}

Any suggestions?

lgi
  • 65
  • 5

3 Answers3

0

Make sure you tell Linq what you want to do to the tables individually

FlashcardsTable.DeleteAllOnSubmit(list);
    SubmitChanges();

This is a simple way to delete all of them

CR41G14
  • 5,464
  • 5
  • 43
  • 64
0

I am 99.999999% sure this is a case of an inproper diagnoses.

Perhaps your data is realy deleted from the database but I am confident it is not because of this piece of code. Show us the real code (in this example you do not have a datacontext so it is some kind of simplification..)

You can profile the sql generated to check if there is a delete in there. If so, I will be more than glad to add a bounty to your question.

Pleun
  • 8,856
  • 2
  • 30
  • 50
  • Hi. Thanks for replay. The code is real. There is no datacontext, because it is a piece of a method of the class inherited from DataContext (SubmitChanges() == this.SubmitChanges()). I watched the generated sql. After first call of SubmitChanges() no SQLs were generated. After second SubmitChanges() were generated commands, which delete objects od table Flashcard... – lgi Nov 30 '12 at 21:04
  • Well, i think you should read up on how to use Linq2Sql because I do not think you are on the right track. I have never seen a class inherited from DataContext just to do CRUD. You should create them on the fly for a Unit-of-Work... – Pleun Nov 30 '12 at 21:56
  • I created class which makes all DB staff and I inherited it from DataContext because it is simple solution in this case (I dont need to create DataContext object all the time but still work on one instance of DataContext - is it bad idea?). I thought that this post is a common mistake of beginner, but now I see that it is not so obvious and I must work harder to find the solution... Thanks for replies – lgi Dec 01 '12 at 09:27
0

I figured it out. After change declaration of association Flashcard->Category everything works fine. Right code is here:

private EntityRef<Category> _categoryRef = new EntityRef<Category>();
[Association(ThisKey = "CatId", OtherKey = "CategoryId", IsForeignKey = true, DeleteOnNull = true, Storage = "_categoryRef")]
public Category Category
{
    get { return _categoryRef.Entity; }
    set
    {
        if (_categoryRef.Entity != value || !_categoryRef.HasLoadedOrAssignedValue)
        {
            _categoryRef.Entity = value;
        }
    }
}
lgi
  • 65
  • 5