English 中文(简体)
EF code first - not able to update a database row
原标题:

Was trying out some code with the EF "code first" method and ran into a strange problem.

My datacontext:

    public class BookmarkerDataContext : DbContext
    {
        public DbSet<User> Users { get; set; }
        protected override void OnModelCreating(System.Data.Entity.ModelConfiguration.ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<User>().HasKey(u => u.UserId);
            base.OnModelCreating(modelBuilder);
        }
     }

Where the user object is:

   public class User
    {
        public long UserId { get; set; }
        public ICollection<Tag> Tags { get; set; }
    }

In my code I am doing something fairly simple:

public void UpdateUserTags(User user,ICollection<Tag> taglist)
    {
        user.Tags = new List<Tag>(user.Tags.Union(taglist));
        datacontext.Users.Add(user);
        datacontext.SaveChanges();
    }

The user object I am passing to this function is the result of something like:

datacontext.Users.SingleOrDefault(u => u.UserId==id)

Everytime I call the UpdateUserTags function it seems to create a new Row in the User table instead of updating it. Am I doing something wrong here?

最佳回答

@Donald is correct, you need to Attach to the ObjectContext when making updates.

However, that is only if your entity is detached.

If sounds like you have already retrieved the single entity from the graph:

var user = datacontext.Users.SingleOrDefault(u => u.UserId==id);

Which means you don t need to Attach or get it again. Just do this:

var user = datacontext.Users.SingleOrDefault(u => u.UserId==id);
user.Tags = new List<Tag>(user.Tags.Union(taglist));
context.SaveChanges();

However, i wouldn t recommend replacing the entire Tags collection, add the tags:

user.Tags.Add(someTag);

HTH

问题回答

I believe you want to Attach your object to the data context, instead of Adding it.

public void UpdateUserTags(User user,ICollection<Tag> taglist)
{
    datacontext.Attach(user);
    user.Tags = new List<Tag>(user.Tags.Union(taglist));
    datacontext.SaveChanges();
}

Once it is attached, then the context becomes aware of the object. Once you save changes, they should be persisted to the database.

Won t this line

datacontext.Users.Add(user);

Always mark the user record as needing to be ADDED to the users table.

I think you have to DETACH the user from the old context and ATTACH it to the new to properly be able to update the record. but I m no EF wonk so ymmv

This has nothing to do with your particular issue but for lazy loading you re going to want Tags to be marked virtual

public virtual ICollection<Tag> Tags { get; set; }

Also, it looks like you re trying to add new tags for a user (or update their tags) if that is the case then you re going to want to use Attach as Donald suggested





相关问题
Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

NSArray s, Primitive types and Boxing Oh My!

I m pretty new to the Objective-C world and I have a long history with .net/C# so naturally I m inclined to use my C# wits. Now here s the question: I feel really inclined to create some type of ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

How to Use Ghostscript DLL to convert PDF to PDF/A

How to user GhostScript DLL to convert PDF to PDF/A. I know I kind of have to call the exported function of gsdll32.dll whose name is gsapi_init_with_args, but how do i pass the right arguments? BTW, ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...

热门标签