3

LINQ to Entities allows this:

context.User.Select(u => new Person
{
    Name = u.Name,
    Parent = u.Parent.Name
});

I need only two properties of a big User table and I get them using the Select method to create a Person object so I can do some processing with it. The thing is that I do this a lot (like twice a second) and it hurts the GC.

So I decided to pool the Person objects but I have no idea how to update an existing object using LINQ to Entities. I can get it as an anonymous method like above and then assign its properties to the depooled object I guess, then I can return the depooled instance, this would at least make the anonymous instance go away in a lower generation of GC but...

I'd really prefer something like this:

context.User.Select(u => People.Take(u.Name, u.Parent.Name))

Which throws a NotSupportedException.

  • Can I use Entity Framework to update the values of an existing object?
  • If so, how?
  • If not, what alternatives do I have?
Şafak Gür
  • 7,045
  • 5
  • 59
  • 96

2 Answers2

2

Can I use Entity Framework to update the values of an existing object?

No - the Select method is used for projection not updating - what your doing is the correct approach. Alternatively you may find it more efficient to change your Person class to a struct as it consumes less memory.

I think you need to elaborate a little more on "It hurts the GC".

Update

It appears Linq to Entities does not support projecting onto struct's (seems like a limitation to me) - best possible approach then would be to just project onto an anonymous type & then you can map your results onto your Person class using your pooling mechanism e.g.

var users = (from u in context.User
            select new {
                Name = u.Name,
                Parent = u.Parent.Name
            }).ToList().Select(u => People.Take(u.Name, u.Parent));
James
  • 80,725
  • 18
  • 167
  • 237
  • Thanks for the answer but I've got a little confused. First, a SQL expression can't know about the Person class' properties either but EF can assign the results to the properties of a new object which means it basically assigns the properties one by one. Why shouldn't it be able to do that on an existing object while it is able to the same thing of a new instance? – Şafak Gür Nov 03 '12 at 09:21
  • Second, struct is a good idea but I don't want it to be copied over and over again. Would it do any good if I use a struct to select items but assign its properties to a pooled class? I suppose struct would get cleaned up after the method returns unless I assing it to a global field, right? And last; I use that Person instance in a lot of places so it doesn't get cleaned up for a while after I'm done using it (with no references left to it) that cause memory issues in my scenario - that's what I meant with "it hurts the GC". I'll try the struct idea, thank you again. – Şafak Gür Nov 03 '12 at 09:22
  • I think I got the first point wrong with regards to the query not knowing about the type (see update). *"Would it do any good if I use a struct to select items but assign its properties to a pooled class"* - it would definitely be more efficient than creating new instances of `Person` for each record like your doing ATM. *"I use that Person instance in a lot of places"* - is it a singleton class? – James Nov 03 '12 at 09:54
  • No, it is a regular class with a rather long life-span and I create dozens of it every second, that's why pooling them instead of waiting for them to get collected seemed like the right thing to do. I'll try the struct approach and _most likely_ accept this answer, thanks again. – Şafak Gür Nov 03 '12 at 10:00
  • Ah ok, pooling would be the way to go if you find yourself creating *lots* of the classes & they are expensive to setup - probably another reason to look at structs. With your pooling though, how do you know when an object is no longer being used? Do you just set the properties to null? – James Nov 03 '12 at 10:10
  • Turned out structs are not supported in Select method of LINQ to Entities. Throws a NotSupportedException when I try to initialize a struct in Select (and I use the parameterless constructor). – Şafak Gür Nov 06 '12 at 12:15
  • @ŞafakGür seems like a pointless limitation to me. Another alternative is to just use anonymous objects and then map them over to your `Person` classes (which would mean you could use your pooling system). – James Nov 06 '12 at 13:08
  • Yes, it seems like a pointless limitation to me, too. And I guess I can use an anonymous object since its reference will be deleted when the method ends and it will _hopefully_ be collected at the next GC cycle. I'll give it a try, thanks. Could you update your answer since we know that using a struct this way is not an option? – Şafak Gür Nov 06 '12 at 15:41
1

You can not pull only few properties of object from DB. If you want to update it, you have to get complete object, update it and then save changes.

But if you really need to update few fields and don't want to move full object, you can use ExecuteStoredCommand method of context object(MySQL example):

    context.ExecuteStoredCommand("UPDATE table1 SET field1 = @value1 WHERE field2 = @value2", new MySqlParameter("@value1", 1), new MySqlParameter("@value2", 2))

It requires you to write some SQL code, but saves your time, because you don't need to worry about opening connection, creating command and other things, required to user regular connector

d219
  • 2,707
  • 5
  • 31
  • 36
Uriil
  • 11,948
  • 11
  • 47
  • 68