I was reading about anemic data models and rich domain models in DDD. I don't want to follow DDD completely but take rather pragmatic approach and just take some concepts out of it because clean ddd seems like an overkill. What I'm building is Web API (using ASP.NET Core and Entity Framework Core).
I don't want to maintain separate DTOs just for serializing and deserializing my models.
And I want to make most of the things like service layer and my controllers generic. Because it's mostly CRUD and logic is repeating - a lot of boilerplate.
I'm not planning to use any other ORM other than EF Core.
EF Core allows mapping to backing fields:
https://ardalis.com/encapsulated-collections-in-entity-framework-core https://technet.microsoft.com/en-us/mt842503.aspx
Is it fine if I will design my models like this and at the same time use them as my DTOs for serialization and deserialization?
public class Player
{
[JsonIgnore]
public int Id { get; set; }
[NotMapped, Required]
public PlayerInfo ActiveInfo { get; set; } // setter must be public to allow deserialization (or use custom resolver for json net)
[JsonIgnore]
public ICollection<PlayerInfo> PlayerInfos { get; set; } = new HashSet<PlayerInfo>();
private Player()
{
}
public Player(PlayerInfo info)
{
info.IsActive = true;
PlayerInfos.Add(info);
}
public void SetActiveInfo(PlayerInfo playerInfo)
{
var currentlyActiveInfo = PlayerInfos.SingleOrDefault(info => info.IsActive);
if (currentlyActiveInfo != null)
{
currentlyActiveInfo.IsActive = false;
}
playerInfo.IsActive = true;
PlayerInfos.Add(playerInfo);
ActiveInfo = playerInfo;
}
}
This is controller:
public class PlayerController
{
private readonly DbContext _dbContext { get; set; }
private readonly DbSet<Player> _players { get; set; }
public PlayerController(DbContext dbContext)
{
_dbContext = dbContext;
_players = dbContext.Set<Player>();
}
// Create new player
[HttpPost]
public ActionResult<Player> Post([FromBody] Player player)
{
if (!ModelState.IsValid)
{
//Handle validation error
}
// No service layer for the sake of simplicity.
player.SetActiveInfo(player.ActiveInfo); // will use _activeInfo
_players.Add(player); // begins tracking entity
if (_dbContext.Save() == 0)
{
// handle error
}
return player;
}
}
_playerInfos
loaded in EF core. Is this actually working as intended? If not, this question belongs on Stack Overflow. \$\endgroup\$_playerInfos
is invalid inSetActiveInfo
. But it's always problematic to change code significantly while it's under review, because even when it's a property I have some reservations, but obviously not the same ones. Maybe you get away with it in this case because the current answer is generic enough to cover both situations. \$\endgroup\$