tags:

views:

681

answers:

4

I have an object in SQL (A) that has a many to many relation ship with another object (B). I'm currently building an API layer dll that will allow the user to assign objects of type B into type A. Right now the user would retrieve a list of entries of type A and a list of entries of type B using different LINQ data contexts. The problem is it the data context associated with A treats any objects from the data context associated with B as if they were new and tries to insert them when I call SubmitChanges(). Is there a way to tell data context A that these objects already exist and don't need to be created? The code I'd like to write looks something like this (I'll call A service and B output):

List<Service> svcs = Service.GetServices();
List<Output> outs = Output.GetOutputs();

svcs[0].OutputCollection.Add(outs);
svcs[0].Save();

Each Service object in my example has a reference to the data context that pulled it from the database and the Save function calls DataContext.SubmitChanges(); The code above throws an exception because it tries to add the Output that already exists back to the table.

I know this was long and I'm not sure I explained my problem well. Any insight or suggestions would be helpful.

A: 

I ran into this same issue, I couldn't come up with an elegant solution. My only solution I found was to either use "stitching," or to use reflection.

Stitching looks something like this.

Person existingPerson - DB.GetPerson(1); existingPerson.BirthDate = newPerson.BirthDate; existingPerson.JobTitle = newPerson.JobTitle;

I once read something about using a callback but I can't find it for the life of me.

Chad Moran
+2  A: 

I actually found a different sort of solution and now i feel kind of stupid for even asking the question. What I did inside the Service.Outputs.Add() method was really the problem:

public void Add(Output output)
{
    OutputCollectionItem oci = new OutputCollectionItem();
    oci.item = output;
    this.OutputCollection.Add(oci);
}

What I should have done is:

public void Add(Output output)
{
    OutputCollectionItem oci = new OutputCollectionItem();
    oci.itemID = output.itemID;
    this.OutputCollection.Add(oci);
}
Mykroft
A: 

I think you'll have to detach the objects from A and B, than link them and do an Attach on your context to reattach them.

so:

// this remains
List<Service> svcs = Service.GetServices();
List<Output> outs = Output.GetOutputs();

svcs[0].OutputCollection.Add(outs);
svcs[0].Save();

// this changes
public class Service
{
    public static List<Service> GetServices()
    {
       var context = new Context();
       var result = context.ServiceSet.ToList();
       result.ForEach(e => context.Detach(e));
       return result;
    }
    public void Save()
    {
       var context = new Context();
       context.Attach(this); // will retach myself and all of my child entities.
       context.SaveChanges();
    }
}

public class Output
{
    public static List<Output> GetOutput()
    {
       var context = new Context();
       var result = context.OutputSet.ToList();
       result.ForEach(e => context.Detach(e));
       return result;
    }
}
Davy Landman
I can't see a Detach method on my context.
Daniel O
If your using entity framework is should be there, http://msdn.microsoft.com/en-us/library/system.data.objects.objectcontext.detach.aspx .
Davy Landman
A: 

Another solution would be to share your context..

If you use an IoC container you could let the container manage the lifetime of your context, for instance in a website it's a good idea to couple the lifetime of your context per request.

Davy Landman