HappyCoding HappyCoding - 1 month ago 6
ASP.NET (C#) Question

When do we need data classes?

Im using asp.net core. Here is the basic way to use model with controller.

public class BookController : Controller
{
private readonly ApplicationDbContext _context { get; set; }

public BookController(ApplicationDbContext context)
{
_context = context;
}

public IActionResult Create(Book model)
{
// adding new model
}

public IActionResult Edit(Book model)
{
// modifying the model
}

public IActionResult Delete(Book model)
{
// removing the model
}
}


My question: when shall/should I implement the code inside the controller? When shall/should I implement it in another class?

Something like this:

public interface IBook
{
int Add(Book book);

int Update(Book book);

int Remove(Book book);
}

public class BookData : IBook
{
private readonly ApplicationDbContext _context { get; set; }

BookData(ApplicationDbContext context)
{
_context = context
}

public int Add(Book model)
{
// ...

return _context.SaveChanges();
}

// other implements...
}


Then, calling it inside controller:

public IActionResult Create(Book model)
{
var bookData = new BookData(_context);
int result = bookData.Add(model);

// ...
}


For the interface, I think it may be useful for the case: I have many controllers that require same action/method names.

Example:
MessageController
requires 3 actions/methods at least (
Create/Add
,
Edit/Update
,
Delete/Remove
). It's same to
NotificationController
class,
CommentController
class...

So, the interface can be improved to:

public interface IMyService<T> where T : class
{
int Add(T model);

int Update(T model);

int Remove(T model);
}

public class MyService<T> : IMyService<T> where T : class
{
private readonly ApplicationDbContext _context { get; set; }

public MyService(ApplicationDbContext context)
{
_context = context;
}

public int Add(T model)
{
Type type = typeof(model);

if (type == typeof(Book))
{
// adding new book model
}
else if (type == typeof(Comment))
{
// adding new comment model
}

// ...

return -1;
}

// other implements...
}


Do I misunderstand something?

Answer

If I read it correctly with data classes you actually means repository (which is an abstraction over the persistence layer). You should always encapsulate persistence logic behind a class (be it via repository pattern, command/query pattern or request handler) and use it instead of directly using the context in your service classes.

That being said, you can directly inject your BookData to your controller instead of the ApplicationDbContext. One thing you should consider you lose in your current implementation is the Unit of Work pattern. Right now, every add will instantly persist the data.

This may not be what you want, so you should move the _context.SaveChanges(); outside of the Add/Remove/Update methods and call it explicitly. This allows you to insert i.e. 10 records and if one of them fails, nothing will be persisted to the database.

But if you call _context.SaveChanges(); after each insert and you get an error in the 8th (of 10) records, then 7 get persisted and 3 will be missing and you get inconsistent data.

Controller shouldn't contain any logic at all, only do short validation of the input model (ModelState.IsValid check) and if its okay, call the services which do all the logic and report the result back to the user. Only in very simple tutorials and guides logic is put into the controller action for reasons of simplicity. In real world applications you should never do that. Controllers are much harder to unit test than service classes.

Comments