Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stay DRY with DTO's

Currently I'm creating a web interface for FreeRADIUS. It's just a small app, to simplify mutations for Shell- and SQL-lazy co-workers. I created a Entity Framework model for the database and want to encapsulate it by using the facade pattern. So I created a DTO class called Account. It stores data aggregated from three different tables. This is what Account.cs looks like:

public class Account
{
    public int? Id { get; set; }
    public string UserName { get; set; }
    public string Password { get; set; }
    public string GroupName { get; set; }
    public string IpAddress { get; set; }
    public string Route { get; set; }
}

This is the method I assemble and return a single Account-DTO.

Account Get(string userName)
{
    // Get the values from the database.
    var check = _entities.Checks.Single(x => x.UserName == userName);
    var userGroup = _entities.UserGroups.Single(x => x.UserName == userName);
    var ipReply = _entities.Replies.Single(x => x.UserName == userName && x.Attribute == "Framed-IP-Address");
    var routeReply = _entities.Replies.Single(x => x.UserName == userName && x.Attribute == "Framed-Route");

    // Populate the DTO
    var account = new Account
    {
        UserName = check.UserName,
        Password = check.Value,
        GroupName = userGroup.GroupName
    };

    if (ipReply != null) account.IpAddress = ipReply.Value;
    if (routeReply != null) account.Route = routeReply.Value;

    return account;
}

And this is the method to update the database by a user-submitted Account-DTO

void Update(Account account)
{
    // Get the values from the database. Again.
    var check = _entities.Checks.Single(x => x.UserName == account.UserName);
    var userGroup = _entities.UserGroups.Single(x => x.UserName == account.UserName);
    var ipReply = _entities.Replies.Single(x => x.UserName == account.UserName && x.Attribute == "Framed-IP-Address");
    var routeReply = _entities.Replies.Single(x => x.UserName == account.UserName && x.Attribute == "Framed-Route");

    // Update the possible attributes
    check.Value = account.Password;
    userGroup.GroupName = account.GroupName;
    ipReply.Value = account.IpAddress;
    routeReply.Value = account.Route;

    _entities.SaveChanges();
}

As you can see, I use the exact same code to retrieve data from the database. How can I DRY this code up?

like image 596
Sandro Avatar asked Apr 23 '12 15:04

Sandro


1 Answers

Why not to simply extract shared code to local class

class AcccountFieldsByName {
// check, userGroup, ipReply, routeReply

    static AcccountFieldsByName Read(... _entities, string userName)    
    {
    return new AcccountFieldsByName {
        check = _entities.Checks.Single(x => x.UserName == userName),
        userGroup = _entities.UserGroups.Single(x => x.UserName == userName),
        ipReply = _entities.Replies.Single(x => x.UserName == userName && x.Attribute == "Framed-IP-Address"),
        routeReply = _entities.Replies.Single(x => x.UserName == userName && x.Attribute == "Framed-Route"),
        }
    }
}
like image 58
Alexei Levenkov Avatar answered Oct 03 '22 16:10

Alexei Levenkov