Darf
Darf

Reputation: 2585

How to improve this code about EntityCollections<TEntity>?

This is the code which I'm not convinced. Please check how I'm passing as parameter the entity Collection.

public ExamProduced GetExamProduced(XElement xml)
{
    var examProduced = new ExamProduced
    {
        ExamProducedID = (int)xml.Attribute("ExamID"),
        Date = (DateTime)xml.Attribute("Date"),
        Seed = (int)xml.Attribute("Seed"),
        //Exercises = GetExercises(xml)
    };

    GetExercises(xml, examProduced.Exercises);
    return examProduced;
}

public void GetExercises(XElement xml, EntityCollection<Exercise> entityCollection)
{
    var objs =
        from objective in xml.Descendants("Objective")
        where (bool)objective.Attribute("Produced")
        let id = (int)objective.Attribute("ID")
        let id2 = (Objective)entityService.Objectives.Where(o => o.ObjectiveID == id).FirstOrDefault()
        select new Exercise
        {
            Objective = id2,
            MakeUp = ...
            Quantify = ...
            Score = ...
        };

    foreach (var exercise in objs)
    {
        entityCollection.Add(exercise);
    }
}

If not, I'll receiving an error. Like this with this code.

public ExamProduced GetExamProduced(XElement xml) 
{ 
    var examProduced = new ExamProduced 
    { 
        ExamProducedID = (int)xml.Attribute("ExamID"), 
        Date = (DateTime)xml.Attribute("Date"), 
        Seed = (int)xml.Attribute("Seed"), 
        Exercises = GetExercises(xml) 
    }; 

    return examProduced; 
} 

public EntityCollection<Exercise> GetExercises(XElement xml) 
{ 
    var objs = 
        from objective in xml.Descendants("Objective") 
        where (bool)objective.Attribute("Produced") 
        let id = (int)objective.Attribute("ID") 
        select new Exercise 
        { 
            ExerciseID = id, 
            MakeUp = (bool)objective.Attribute("MakeUp"), 
            Quantify = (byte)(int)objective.Attribute("Quantify"), 
            Score = (float)objective.Elements().Last().Attribute("Result") 
        }; 

        var entityCollection = new EntityCollection<Exercise>();

        foreach (var exercise in objs)
            entityCollection.Add(exercise);

        return entityCollection;
} 

enter image description here

The error I am getting is below:

InvalidOperationException was unhandled.

The object could not be added to the EntityCollection or EntityReference. An object that is attached to an ObjectContext cannot be added to an EntityCollection or EntityReference that is not associated with a source object.

Upvotes: 2

Views: 516

Answers (1)

user743382
user743382

Reputation:

I hope that from the comments I'm understanding you correctly... If not, I'll update this answer.

Firstly, your EntityCollection<Exercise> GetExercises(XElement xml) is not going to work. As the error message says, you cannot construct a random EntityCollection like that: the EntityCollection needs the object to be attached to the context because it automatically synchronises its list with the context. And since you aren't saying what to attach it to anywhere, it won't work. The only way to make it work would be to avoid creating an EntityCollection in the first place.

Your void GetExercises(XElement xml, EntityCollection<Exercise> entityCollection) procedure could work. However, you need to make sure to actually have an EntityCollection<Exercise> instance to be able to call it. The way you're creating your ExamProduced object, it isn't attached to the context by the time you return from GetExamProduced, so it isn't possible to have a EntityCollection<Exercise> property for it at that point.

Perhaps the easiest way to get things working would be to pass your context to the GetExamProduced method, and let them get attached to the context automatically. I'm assuming it's a common ObjectContext, but you can update it as needed:

public ExamProduced GetExamProduced(XElement xml, YourContext context)
{
    var examProduced = new ExamProduced()
    {
        ExamProducedID = (int)xml.Attribute("ExamID"),
        Date = (DateTime)xml.Attribute("Date"),
        Seed = (int)xml.Attribute("Seed")
    };
    context.ExamsProduced.Attach(examProduced);
    LoadExercises(xml, context, examProduced);
    // examProduced.Exercises should be available at this point
    return examProduced;
}

public void LoadExercises(XElement xml, YourContext context, ExamProduced examProduced)
{
    foreach (var exercise in
        from objective in xml.Descendants("Objective")
        where (bool)objective.Attribute("Produced")
        let id = (int)objective.Attribute("ID")
        let id2 = (Objective)entityService.Objectives.Where(o => o.ObjectiveID == id).FirstOrDefault()
        select new Exercise
        {
            ExamProduced = examProduced,
            Objective = id2,
            MakeUp = ...
            Quantify = ...
            Score = ...
        }))
    {
        context.Exercises.Attach(exercise);
    }
}

I don't know if these are new objects that should be added in the database, or if these objects are expected to exist in the database already. I've assumed the latter. If the former, .Attach should be updated to .AddObject in two places.

Is this what you're looking for, or did I misunderstand?

Upvotes: 0

Related Questions