0

This is a bit of a long one, so get yourself a coffee (other quality libations are available).

In an effort to write as little code as possible, keep my apps simple, testable, maintainable and clean, and to turn apps around in quickly.

I'm using a really simple method I wrote to copy from MVC objects to EF objects to save me writing loads of code when I have objects with loads of properties. In fact, I don't care what the object is or how many properties it has. I just want to copy it without prepping loads of code in a map or somewhere.

Please don't start off on view models and all that, and quoting me the big book of Microsoft. All I'm looking for a little advice from my peers and the community in general about AutoMapper The example here is simple so you can see what I'm getting at.

What I didn't want to do and I've seen it lots, was:-

item ... //the original item populated from somewhere, MVC database, who cares, its got stuff in it

Item newItem = new Item();

newItem.prop1 = item.prop1;
newItem.prop2 = item.prop2;
newItem.prop3 = item.prop3;
newItem.prop4 = item.prop4;
//... you get the idea

or even this ...

Item newItem = new Item {  
    prop1 = item.prop1,
    prop2 = item.prop2,
    prop3 = item.prop3,
    prop4 = item.prop4,
    //... you get the idea
}

So I came up with this. A function called CopyObject that does excatly what I want it to do, so I don't have to care about any objects or how many properties it has, I write one line of code anywhere I need to that does all the work for me. See the example below

//show the item in a view, typically a bootstrap popup dialog
public IActionResult EditItem(int ID)
{
    Item item = _dbContext.Items.Where(i => i.ID == ID).FirstOrDefault();

    if (item == null)
        item = new Item { ... property defaults ... };

    return View(item);
}

//save the item from the view
[HttpPost]
public JsonResult EditItem(Item item)
{
    Item newItem = _dbContext.Item.Where(i => item.ID).FirstOrDefault();
    if (newItem == null)
    {
        newItem = newItem {... property defaults ... };
        _dbContext.Items.Add(newItem);
    }

    //here is the fun part
    CopyObject(item, newItem, ...ignore some properties);

    _dbContext.SaveChanges();

    return new JsonResult( new { result = "success", message = "Updated" });
}

CopyObject is my function, it does nothing clever except it uses reflection to copy properties from one object to another (EF)object without losing the connection to EF. CopyObject looks like this (below). I won't bore you with the implementation, but simply, it uses reflection to copy properties between any two objects.

At the moment it only copies from the top-level because that's all I need it to do right now, but it wouldn't be a massive stretch to get it to copy a hierarchy of stuff.

It doesn't actually care that the object types match, it doesn't care that the property types match. It only cares that if finds properties on each object with the same name, and it will then attempt to copy the values. You can also specify properties not to copy.

    /// <summary>
    /// Copies the values of the properties from one object to another object with the same properties if they exist.
    /// This will try to copy from any two objects whether they are the same object type or not
    /// </summary>
    /// <param name="CopyFrom">The object to copy property data from</param>
    /// <param name="CopyTo">The object to copy property data to</param>
    /// <param name="DontCopy">A (string) list field names not to be copied</param>
    /// <returns>True if at least one property was copied, otherwise false</returns>
    public bool CopyObjects(object CopyFrom, object CopyTo, params string[] DontCopy) {...}

There is nothing wrong with my code it works perfectly fine just the way I need it to. I don't have any extra work to do when I start a new project no matter how many properties any of the objects have. I just import that

Anyway, because I'm not published or any kind of authority my code is getting frowned upon. I've been told AutoMapper can do the same thing but I can't seem to make it. I always get a disconnected object that I then have to do some tomfoolery to get it back into the EF and ultimately database.

So my question is. How do you acheive the same thing using Automapper without lots of code?. Remember my goal is not to have to write loads of code, in prep or in line.

djack109
  • 1,261
  • 1
  • 23
  • 42
  • This could be managed by a DbContext after an entity is added by using `dbContext.Entry(newItem).CurrentValues.SetValues(item);` – Jota.Toledo Sep 13 '19 at 09:46
  • What have you tried with AutoMapper? – Jota.Toledo Sep 13 '19 at 09:49
  • 1
    AutoMapper does the same thing in the sense that you're building your own version of AutoMapper: just not nearly a feature complete. However, you question basically boils down to "how do I use AutoMapper?" which is far too broad. Read the docs. There's tons of tutorials and such online as well. If you have a *specific* issue, we can help you with that, but you're going to have to just learn how to use it yourself. – Chris Pratt Sep 13 '19 at 12:41
  • @Jota.Toledo. Actually its more fundamental than that and I should have explained better. What I want to have is **zero configuration**. From what I have read and tried you can't do that with auto-mapper. You have to do some (pre) configuration and that's what I am trying to avoid. I'd love to be able to do something like `autoMapper.Map(a, b, ignore-c, ignore-d)` – djack109 Sep 14 '19 at 12:39

1 Answers1

0

AutoMapper could ignore properties(such as Name in following example) by using below code

public class MyProfile : Profile
{
    public MyProfile ()
    {
        CreateMap<Item, Item>().ForMember(x => x.Name, opt => opt.Ignore()) ;

    }
}

Your Action:

var newItem = _mapper.Map<Item, Item>(item);

Refer to

Ignore mapping one property with Automapper

https://medium.com/ps-its-huuti/how-to-get-started-with-automapper-and-asp-net-core-2-ecac60ef523f

Ryan
  • 19,118
  • 10
  • 37
  • 53
  • Thanks for that. I've been investigating AutoMapper, and for what I wanted, which is zero-configuration, AutoMapper can't do that. That said its a pretty handy tool very extensive for more complex operations, which I don't need atm. – djack109 Sep 17 '19 at 13:07