0

I'm just discovering LINQ and finding it great. One problem thoush is that I have to copy a lot of fields during an update in a 3-tier (layer) application. The algorithm I used shows a typical LINQ update of a class.

  1. I receive the object FromPresentation from the presentation layer.
  2. I use LINQ to get the object with the same ID from the database.
  3. I change a lot of fields
  4. Save the changes.

And the corresponding code:

using (var ctx = new AppDataDataContext())
{
    var OBJ =
        (from Usu in ctx.usuarios
         where Usu.ID == FromPresentation.ID
         select Usu).SingleOrDefault();
    if (OBJ != null)
    { 
        OBJ.Nome = FromPresentation.Nome;
        OBJ.NomeCurto = FromPresentation.NomeCurto;
        OBJ.Login = FromPresentation.Login;
        OBJ.Senha = FromPresentation.Senha;
        OBJ.SuperUsuario = FromPresentation.SuperUsuario;
        OBJ.Ativo = FromPresentation.Ativo;
             // a lot more fields                   
        ctx.SubmitChanges();
        return OBJ.ID;
    }
}

The problem is that I have a lot of fields. I even tried using reflection (using this question for guidance) to copy the fields but LINQ is not notified of the changes so it doesn't save anything.

How can I use reflection to copy values to a LINQ object so it can be updated in the database?

Community
  • 1
  • 1
Fabio
  • 1,037
  • 1
  • 10
  • 22
  • Does your database objects have a primary key declared? Using reflection should work (though you would be better off using tools as BrokenGlass mentions) but won't unless you have declared a primary key. Without it, no code would be generated to make those updates on your database objects. – Jeff Mercado Jul 22 '11 at 23:33
  • Jeff, I don't see how to do that using Linq. – Fabio Jul 22 '11 at 23:48
  • 1
    See: [LINQ not updating on .SubmitChanges()](http://stackoverflow.com/questions/206532/linq-not-updating-on-submitchanges). Whether you're using reflection or a tool like automapper won't matter if your objects do not declare primary keys. – Jeff Mercado Jul 22 '11 at 23:57
  • Jeff, all my tables have primary keys and update fine if I set properties one by one. – Fabio Jul 23 '11 at 09:37
  • Hi Fabio! Could you make it work? I'm having the same issue! Thanks – André Miranda Sep 05 '11 at 05:57

2 Answers2

4

Don't use reflection for this, that would be reinventing the wheel - use a mapper like AutoMapper to do the work for you.

AutoMapper uses a fluent configuration API to define an object-object mapping strategy. AutoMapper uses a convention-based matching algorithm to match up source to destination values. Currently, AutoMapper is geared towards model projection scenarios to flatten complex object models to DTOs and other simple objects, whose design is better suited for serialization, communication, messaging, or simply an anti-corruption layer between the domain and application layer.

BrokenGlass
  • 158,293
  • 28
  • 286
  • 335
  • Broken Glass, Just tryed AutoMapper and it seens to have the same problem reflection does. The Properties change on the object but somehow it does not notify Linq that the record changed. I think it's because it changes the fields directly and not the properties. Linq needs us to use the properties so it gets notified that something changed. – Fabio Jul 22 '11 at 23:42
  • OK, I defined one of the partial methods of the class and I can tell that LINQ id firing the events correctly when I use AutoMaper, so my theory above is flawed. Then, why does not LINQ save the record when I use reflection or AutoMapper to copy the fields ? – Fabio Jul 23 '11 at 14:10
0

You could try updating the properties rather than the fields.

eg

 private static void UpdateForType(Type type, MyObject source, MyObject destination)
 {
    var myObjectProperties = type.GetProperties(
        BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);

    foreach (PropertyInfo pi in myObjectProperties)
        pi.SetValue(destination, pi.GetValue(source, null), null);      
 } 
sgmoore
  • 15,694
  • 5
  • 43
  • 67