Brian Tacker
Brian Tacker

Reputation: 1122

FirstOrDefault doesn't seem to be calling database after Add

I have a web service that sends a message through a third party service, then that service updates my database by setting the "Sent" flag (it sets it to 1 for success and -1 for failure). And my web service is using a code first entity framework model.

Im sending the message, inserting a message record in my database, then waiting for the 3rd party service to update the sent flag:

var messageId = sendMessage();
using (var db = new DBModel())
{
    db.Messages.Add(new Message()
    {
        MessageId = messageId,
        Sent = 0,
        // Other properties
    });
    db.SaveChanges();
    bool sent = false;
    while (!sent)
    {
        int i = db.Messages.FirstOrDefault(m => m.MessageId == messageId).Sent;
        if (i == -1) throw new Exception();
        sent = i == 1;
    }
}

The problem is that every time I call "FirstOrDefault", 'Sent' is always returning 0. But if I manually check the record in the database, Sent is set to 1 because it is getting set by the third party service. It seems as though the FirstOrDefault is returning the value from cache, but I was under the impression that anytime you call FirstOrDefault it calls the database.

Does anyone have an explanation for this? And is there any way to get around it?

Thanks.

Upvotes: 2

Views: 1059

Answers (3)

Reza Aghaei
Reza Aghaei

Reputation: 125277

As another option you can disable caching of objects in context:

db.Messages.AsNoTracking().FirstOrDefault(m => m.MessageId == messageId)

DbExtensions.AsNoTracking Method (IQueryable)

Returns a new query where the entities returned will not be cached in the DbContext or ObjectContext.

Upvotes: 1

Jonathan cartwright
Jonathan cartwright

Reputation: 142

One think you could do that should work would be to detach the record that you just added from your entity context. That way entity framework would be forced to fetch it from the database again.

To do that, just call detach (messageObj) where messageObj is a reference to the message you added to the table. Remember to do that after you call save changes otherwise your record won't get created.

Upvotes: 1

Rob
Rob

Reputation: 27367

Change your code to this:

DBModel db;
var messageId = sendMessage();
using (db = new DBModel())
{
    db.Messages.Add(new Message()
    {
        MessageId = messageId,
        Sent = 0,
        // Other properties
    });
    db.SaveChanges();
} 

bool sent = false;
while (!sent)
{
    using (db = new DBModel())
    {
        int i = db.Messages.FirstOrDefault(m => m.MessageId == messageId).Sent;
        if (i == -1) throw new Exception();
        sent = i == 1;
    }
}

Or:

var messageId = sendMessage();
using (var db = new DBModel())
{
    var message = new Message()
    {
        MessageId = messageId,
        Sent = 0,
        // Other properties
    };

    db.Messages.Add(message);
    db.SaveChanges();
    bool sent = false;
    while (!sent)
    {
        db.Detach(message); // <<< This part
        message = db.Messages.FirstOrDefault(m => m.MessageId == messageId);
        var i = message.Sent;
        if (i == -1) throw new Exception();
        sent = i == 1;
    }
}

Upvotes: 2

Related Questions