1

I have a problem when using the new Entity Framework 4.1. I started testing it a few days ago, and I am still new to the whole POCO concept and this new API.

Anyway, while doing some coding I created something like this:

public Tag GetTagWithName(string name)
{
    if (db.Tags.SingleOrDefault(q => q.Name == name) == null)
    {

        return new Tag { Name = name };
    }
    else
    {
        return db.Tags.SingleOrDefault(q => q.Name == name);
    }
}

Which is supposed to check in the database if the Tag this such a name already exists, and I am using this function in this piece of code:

if (tags != null)
{
    foreach (HtmlNode tagNode in tags)
    {
        string tagString = tagNode.InnerText.Remove(0, 1);
        Tag tag = TagRep.GetTagWithName(tagString);
        pic.Tags.Add(tag);
    }
}
if (context.Pictures.Any(q => q.Link == pic.Link))
{
    continue;
}
else
{
    context.Pictures.Add(pic);
}
context.SaveChanges();

Which is basically adding Tags to newly created photos, check if the photo is in database already and than if not add it to database, and invoke SaveChanges() after every picture.

Well my problem it, that during execution function GetTagWithName causes an error "Sequence contains more than one element" on getting "SingleOrDefault", which shouldn't happen, because I check the whole database before adding any new tag, using this function to check if the tag is already in DB.

From what I saw in my code, the situation happens because of the fact, that even if I add to the Picture a Tag object which I took from database, it still later on adds it as a new object to the Tags table.

Is there any explaination for that?

3
  • Where does the 'db' variable come from in your GetTagWithName method? Is it the same as the context in the second codeblock? Commented Oct 3, 2011 at 11:06
  • No, these are two different variables. Commented Oct 3, 2011 at 16:45
  • Generally I agree with @macias - you should change your structure, but as a quick solution you could try passing the context variable into the GetTagWithName method and using it instead of the db variable. See if this fixes your problem. Commented Oct 4, 2011 at 8:20

1 Answer 1

3

Several things things. One, you are doing it wrong:

which shouldn't happen, because I check the whole database before adding any new tag, using this function to check if the tag is already in DB.

Databases are capable of checking such constraints, so use the database, not the code.

Second thing -- your code is not only inefficent (you hit db twice) but buggy too. You check the name against the database, let's say it does not exist, so you add a tag, then you check the same name, it still does not exists, so you add it again!

You save it, and then you cannot get single record, because you just saved 2 records of the same name.

Sign up to request clarification or add additional context in comments.

4 Comments

Totally agree. Best the OP does some more reading/tutorials on EF.
Problem is I tested it even in situation when I am sure that after one save, when the data is already in the DB, it still occurs... Let's say I have a tag named "Nature", and when I can already see that tag in the DB, the "GetTagWithName" method is returning that object from the DB, yet still when I add it to the picture with this line of code: pic.Tags.Add(tag); I still end up with the new Tag record in the DB... So ifit is a wrong approach to do that I would be really grateful for pointing me in the right direction.
Just in case, could you set a breakpoint on returning Tag from DB, to be 100% sure it is fetched from DB? Please note: EF (as ORM) does some magic behind, I prefer using direct foreign key id when attaching external data, instead of full objects (in my case it is cache, but your case is similar -- you use two distinct data contexts).
I did set the breakpoints there, also went through the wole code line by line, and I am rather sure of the error... I am aware of the EF magic, and that was my first idea as well, but I am new to EF 4.1 and I am not sure which options I should turn off to get the result I want...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.