2

I'm at wits end here. The problem is I'm trying to create a new entity in the database, with a db generated identity property, in LINQ to SQL and then create another entity associated with the first one. I'm guessing the problem is that LINQ to SQL cannot insert the second entity without the id from the first entity, which won't be known until the database generates it.

Has anyone else had this problem... if so how did you resolve it? I know I could call SubmitChanges between the creation of the first and the second entity, but this would break the transactional integrity of the program.

Here's a concrete example:

[Table(Name = "Searches")]
public class Search
{
    // Db Generated Key
    [Column(IsPrimaryKey = true, IsDbGenerated = true, AutoSync = AutoSync.OnInsert)]
    public Int32 SearchID { get; set; }

    // Each search can have multiple search parameters
    private EntitySet<SearchParam> searchParams;

    [Association(Storage = "searchParams", ThisKey = "SearchID", OtherKey = "SearchID")]
    public EntitySet<SearchParam> SearchParams
    {
        get
        {
            return searchParams;
        }
        set
        {
            searchParams.Assign(value);
        }
    }
}

[Table(Name = "SearchParams")]
public class SearchParam
{
    [Column(IsPrimaryKey = true, IsDbGenerated = true, AutoSync = AutoSync.OnInsert)]
    public Int32 SearchParamID { get; set; }

    [Column]
    public String ParamValue { get; set; }

    // Each search param is associated with one search
    [Column]
    public Int32 SearchID { get; set; }

    private EntityRef<Search> search = new EntityRef<Search>();

    [Association(Storage = "search", ThisKey = "SearchID", OtherKey = "SearchID", IsForeignKey = true)]
    public Search Search
    {
        get
        {
            return search.Entity;
        }
        set
        {
            search.Entity = value;
        }
    }
}

So with the above code, if I were to do something like the following, .NET gives me a NullReferenceException on SubmitChanges:

using (SampleDataContext context = new SampleDataContext())
{
    Search search = new Search();
    search.SearchParams.Add(new SearchParam() { ParamValue = "...paramvalue..." });
    context.Searches.InsertOnSubmit(search);
    context.SubmitChanges();
}
George Lanetz
  • 300
  • 5
  • 18
Micah Hahn
  • 400
  • 2
  • 11
  • Have you tried inserting your search, submitting changes then adding the params and submitting the changes? – Nico Sep 18 '13 at 02:46
  • 1
    Yes, but like I said that is no longer a transaction... if something goes wrong inserting the params, then the search will not rollback. – Micah Hahn Sep 18 '13 at 03:08
  • Almost all cases of `NullReferenceException` are the same. Please see "[What is a NullReferenceException in .NET?](http://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-in-net)" for some hints. – John Saunders Sep 20 '13 at 18:59

3 Answers3

0

Don't know why yours is not working, but this should work

using (SampleDataContext context = new SampleDataContext())
{
     Search search = new Search();
     SearchParam param = new SearchParam() { ParamValue = "...paramvalue..." })
     param.search = search
     context.searchparams.InsertOnSubmit (param ) // Not sure if this is necessary
     context.Searches.InsertOnSubmit(search);
     context.SubmitChanges();
}

And all in one transaction.

Pleun
  • 8,856
  • 2
  • 30
  • 50
0

It doesn't look to me like you are initializing the SearchParams list before calling add on it. Does this work:

using (SampleDataContext context = new SampleDataContext()) {
    Search search = new Search();
   search.SearchParams = new EntitySet<SearchParam>(); //<-- THIS LINE
    search.SearchParams.Add(new SearchParam() { ParamValue = "...paramvalue..." });
    context.Searches.InsertOnSubmit(search);
    context.SubmitChanges();
}
Matthew
  • 9,851
  • 4
  • 46
  • 77
  • Removed - doesn't change the (I think and sgmoore does too) correct diagnosis of his issue. – Matthew Sep 20 '13 at 19:16
  • @Micah Hahn : For completeness - I would also recommend you instantiate the EntitySet in the constructor of your `Search` object so you don't have to do this everywhere. – Matthew Sep 23 '13 at 14:22
0

Try adding the following to your Search class

    public Search()
    {
        this.SearchParams = new EntitySet<SearchParams >(
         new Action<SearchParams >(this.attach_SearchParams ), 
         new Action<SearchParams >(this.detach_SearchParams ));
    }

    private void attach_SearchParams(SearchParams sp)
    {
        sp.Search = this;
    }

    private void detach_Search(SearchParams sp)
    {
        sp.Search = null;
    }
sgmoore
  • 15,694
  • 5
  • 43
  • 67