how to edit in memory object efficiently in C#

Viewed 76

I am using Entity framework core repository pattern with unit of work (C#) I want to know the effective way of update the object

Model Class

public class Item : IEntity
{
    public string Label { get; set; }
    public double Quantity { get; set; }
    public string Description { get; set; }
    public int DisplayPriority { get; set; }
    public ItemStatus Status { get; set; }
    public string ShopperComment { get; set; }
}

DTOclass

public class ItemDto
{
    public string Label { get; set; }
    public double Quantity { get; set; }
    public string Description { get; set; }
    public int DisplayPriority { get; set; }
    public string ShopperComment { get; set; }

}

Controller code

[HttpPut("{itemId}")]
public async Task<IActionResult> Update(Guid itemId,[FromBody]ItemDto itemDto)
{
    try
    {
        if (!_permissionsManager.UserHasAnAllowedRole(User, new List<string>() { "SuperAdmin", "Administrator", "Item.Update" }))
        {
            return Unauthorized(new ErrorDto("Method not allowed"));
        }

        var item = await _unitOfWork.Items.Get(itemId);

        if (item == null)
        {
            return BadRequest(new ErrorDto("Item does not exist"));
        }


        item.Label = itemDto.Label;
        item.Status = itemDto.Status;
        item.ShopperComment = itemDto.ShopperComment;
        item.Description = itemDto.Description;
        item.Quantity = itemDto.Quantity;
        item.DisplayPriority = itemDto.DisplayPriority;

        await _unitOfWork.SaveChangesAsync();

        return Ok(item.toItemDto());
    }
    catch (Exception x)
    {
        _log.Error("[Update] Failed", x);
        return StatusCode(500, new ErrorDto(x.Message));
    }
}

I don't want the mapping from ItemDto to Item for update Item Object in the controller how can I do that with good flexible way through loose coupling as I don't want to add object dependencies in the controller

2 Answers

Firstly you can declare an interface for your models aka IItem and do in the contract(id you don't want to refer to concrete types in your controllers and worry about coupling):

public interface IItem {
    string Label { get; set; }
    double Quantity { get; set; }
    string Description { get; set; }
    int DisplayPriority { get; set; }
    ItemStatus Status { get; set; }
    string ShopperComment { get; set; }
}

use the inheritance for your particular models - ItemDto : IItem,Item : IItem,IEntity.

After that you can create a specific service for this, like IItemMapper service and declare the method named like UpdateItem(IItem dbItem, IItem updated) and use another built-in method of Entity Framework in order to avoid enumeration for each property - something like:

public void UpdateItem(IItem dbItem, IItem updated) {
    ...
    //injections/ logic/ validation
    await _unitOfWork.Entry(dbItem).CurrentValues.SetValues(updated);
}

In addition, as an option, you can use even Automapper to avoid enumeration of each property.

You are not following the repository pattern at all. The purpose of the repository pattern is to create an abstraction between the data tier (i.e. the database/tables) and the business domain (your classes).

The purpose of that is to reduce complexity and the requirement to both updates the data layer and the business layer when something changes.

Your code does neither.

Then you are missing the point of DTO's. The purpose of those is to redesign the business entities so that they work better in an API (as DTO stands for "Data Transfer Objects"). If you do not do that, there is not really a point in using them. Expose your EF entities directly.

Now, to your actual question. The easiest way is to use a library like automapper which takes care of the copying for you.

Related