Mvvm Light and Entity Framework Core best practices - c#

I'm creating a new UWP application using Mvvm Light and Entity Framework Core. I'm new to these 2 technologies.
I create my model : the Article class is a simple ObservableObject with 3 properties : Id, Référence and Désignation.
My DbContext is the following :
public class UniversalTest1Context : DbContext
{
public DbSet<Article> Articles { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlite("Filename=UniversalTest1.db");
}
}
I'm looking for the best way to manage the DbContext and my different views.
Is it better to create one DbContext for the whole application ? I don't really like that idea.
Do I have to create a DbContext in each ViewModel ? I like this more.
When the user double tap an item in the article list view, I navigate to the article detail view and pass the article to the view model associated to the article detail view. But this already existing article is not related to the DbContext of the Article detail view model.
Is it possible to instantiate the DbContext only when needed ? My prefered option.
For this, I pass the article from the list view model to the detail view model. And then, when the user clicks save I execute something like this :
using (var db = new UniversalTest1Context())
{
db.Articles.Add(article);
await db.SaveChangesAsync();
}
Of course, this works for new articles (insert), but not for existing ones (update).
I have difficulties making up my mind here.
Many thanks in advance,
Julien

In my opinion, you should hide all storing operations by interface (like IArticleRepo or smth like that) and you should use IoC for accessing it (if some class wants to work with Store, it have to declare IArticleRepo in ctor parameters). Also, inside this interface IArticleRepo you can delcare neecessarry operations with Articles, like IArticleRepo.AddArticle(Article a). If you do so, you can choose later, whether you want to create dbcontext for each operation or not OR maybe you want to make IArticleRepo implementation as singletone using IoC container. But such decisions should not affect on other code.
As very simle sample in my code (I showing only this file, whole project is ugly and I will change it) https://github.com/tym32167/arma3beclient/blob/master/src/Arma3BE.Client.Libs/Repositories/PlayerRepository.cs#L23

Related

CQRS - Creating BaseCommandHandler using Mediatr in C#, ASP.net Core

So I learned about Mediatr created by Jimmy Bogard and it really amazed me how we achieve CQRS pattern using Mediatr.
I started to implement it in my application, and then I realized that I might have hundreds of Entities in my application, and for each Entity I am not sure about creating separate commands and queries, that would be just opposite of DRY. So I started writing base commands and handlers.
public abstract class CreateBaseCommand : IRequest
{
}
public abstract class DeleteBaseCommand : IRequest
{
} //... and so on.
And respective handlers.
public abstract class CreateBaseHandler : IRequestHandler<CreateBaseCommand>
{
}
public abstract class DeleteBaseCommandHandler : IRequestHandler<DeleteBaseCommand>
{
}//... and so on.
But I realised, I would still need separate commands for my domain entities, and they will have to derive from their Base commands respectively.
Then I though if I can just put all commands in one and have just one base handler.
public abstract class BaseCommand : IRequest
{
int CommandType
}
public abstract class BaseCommandHandler : IRequestHandler<BaseCommand>
{
public Task<Unit> Handle(BaseCommand request, CancellationToken cancellationToken)
{
if (CommandType == 0)
{
// Create entity
}
if (CommandType == 1)
{
// Update entity
}//.. and so on
}
}
I was wondering if there is more efficient way to do this, I am not very convinced with idea of using CommandType and have one handle method to perform all CRUD operations.
Is this a good approach or should I have separate set of commands for each domain entity?
Technically you should have a separate command for each creation. Adding a base doesn’t get you much, and complicates the structure so I would get rid of that.
The real problem is that you’re thinking of this from the point of view of your data model, not your domain model. You’re creating a command per table row when you should be creating a command per business idea.
For example, say you’re writing a retail system and creating a new order for a registered user, and that order has 5 line items. Looking at this from the data model point of view, you need to send 1 create command for the order and 5 create commands for the line items. What should happen is to send one command AddNewOrderCommand and have the User class handle it. The User class method then creates the new order database row and all line items. How you add the order (what rows to create, etc) is now encapsulated in the method where it belongs instead of your command architecture.
Are you using Domain Driven Design for your app? If not, you should consider it because its very good with complex systems, and if you have hundreds of entities chances are good this qualifies as a complex system. In DDD parlance, the User above is called and Aggregate Root and the Order and Line Item are just entities. You don’t have Create commands for entities, just for the Aggregate Roots. (Note that a class can sometimes be both an aggregate root and a normal entity in another aggregate root. Why this happens and how to handle it is out of scope for this question)
Look through your model and find things that don’t make sense unless they are owned by something else. For example the line item from the example above. Having a line item in my database that’s not related to an order makes no sense. Therefore, all line items should be created by orders. Having an order with no user associated with it also makes no sense. Therefore the user should create the order. A user, however, seems to be the top of the pyramid, so it is the aggregate root and does need a Create command.
If you analyze your domain, you’ll find you don’t need nearly so many Create commands, and so the problem disappears.

EF Context in Model Class

In our Web.API project, we use Entity Framework 6. We have a DataModel class, which contains the DatabaseContext. The DataModel is a [ThreadStatic] Singleton.
Like this:
public class DataModel
{
[ThreadStatic] private static DataModel _instance;
public static DataModel Instance => _instance ?? (_instance = new DataModel());
public DatabaseContext Context { get; private set; }
private DataModel()
{
Context = NewContext();
}
}
Now in one of our (partial) model classes, we use the context like this:
public partial class Job
{
public User CreatedByUser
{
get { return DataModel.Instance.Context.Users.FirstOrDefault(d => d.Username == CreatedBy); }
}
}
We search in another table in the database the corresponding user. This works, but in my opinion, this is not a beautiful solution. Especially if we plan to migrate our project to.NET Core and use dependency injection for the database context.
My Question is, is there a pattern, which solves the problem more elegant? Dependency injection won't work here because Entity Framework generates the model objects. Or would it be better, if we move this code from the partial class to e.g. a util class? But how can we inject there the context?
You generally want to avoid requiring your models to have awareness of their creation and usage context since that knowledge should be top down and not bottom up. Among other reasons, you'll run into design issues like you are experiencing now. You can try to design your way around it at the application level with extension methods, an inversion of control framework, utility methods, pocos, etc, but at the end of the day you are trying to solve a problem that only exists because your underlying database schema is inadequately designed for your intended usage.
For example, your Job table has a reference to the username of the user that created it. Why? It might be possible for usernames to change and any time you want additional critical properties of that user you will need to perform a secondary lookup (like you're doing in your partial class). If you instead have the Job table maintain a foreign key to the User table, you can just use a navigation property on the C# side to get the full user object as long as the appropriate related entities are included in the query. You wouldn't even need the partial class and your database schema would become more maintainable as an added bonus.
Sometimes it's best to simplify the database design to simplify the code.

How to add custom methods with database logic

I created an application with this architecture:
MyProject.Model: Contains POCO. Example:
public class Car
{
public int Id { get; set; }
public string Name { get; set; }
}
MyProject.Repositories: Contains repositories and UnitOfWork
public class UnitOfWork
{
// ...
public Repository<Car> Cars { get; set; }
// ...
}
public class Repository<T>
{
// ...
// Add / Update / Delete ...
// ...
}
MyProject.Web: ASP.Net MVC application
Now I want to find a way to interact with data by using methods. For example in MyProject.Model.Car I want to add a method that will get data with non-navigation properties, a method named `GetSimilarCars()'. The problem is that the repository cannot interact with other repositories and thus cannot perform operations on the database.
I don't really know how to do this in a simple manner and what is the best place in my architecture to put this.
Another example could be UserGroup.Deactivate(), this method would deactivate each user and send them a notification by email. Of course I can put this method in the Web application Controller but I think this is no the place to put such code that could be called in many places in the application.
Note: I am using Entity Framework.
Any suggestion on how to implement such operations?
This type of stuff goes into your DAL (essentially your unit of work and repository, in this limited scenario). However, this is a pattern that bit me when I first starting working with MVC. Entity Framework already implements these patterns; your DbContext is your unit of work and your DbSet is your repository. All creating another layer on top of this does is add complexity. I personally ended up going with a service pattern instead, which merely sits on top of EF and allows me to do things like someService.GetAllFoo(). That way, the use of Entity Framework is abstracted away (I can switch out the DAL at any time. I can even remove the database completely and go with an API instead, without having to change any code in the rest of my application.) but I'm also not just reinventing the wheel.
In a service pattern, you're specifically only providing endpoints for the things you need, so it's a perfect candidate for things like GetSimilarCars, as you simply just add another method to the service to encapsulate the logic for that.
I would assume that your Business Layer (BL) would be communicating with your Data Access Layer (DAL). That way from your BL you could reach out to different repositories in DAL. That would solve your problem of repositories not being able to share data (that data would be shared through BL).
See here: N-tier architecture w/ EF and MVC
I did not quite get you question but this is how you assign the values. And add it into a collection
public class Repository<T>
{
List<car> _lstCar=new List<car>();
//Add
car cobj=new car();
cobj.Id="1234";
cobj.Name="Mercedes";
_lstCar.Add(cobj);
}

Entity Framework + Autofac: How to properly reload mappings / configurations?

BACKGROUND:
Our core framework loads all entity framework mappings from itself, the main application and any modules we have installed by using an interface (below):
public interface IEntityTypeConfiguration : IDependency
{
}
and we have a DbContext in our core framework like this, which loads all the mappings:
public class DefaultDbContext : DbContextBase
{
private readonly Lazy<IEnumerable<IEntityTypeConfiguration>> configurations;
public DefaultDbContext(Lazy<IEnumerable<IEntityTypeConfiguration>> configurations)
: base()
{
this.configurations = configurations;
Configuration.ProxyCreationEnabled = false;
}
public DefaultDbContext(string connectionString, Lazy<IEnumerable<IEntityTypeConfiguration>> configurations)
: base(connectionString)
{
this.configurations = configurations;
Configuration.ProxyCreationEnabled = false;
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
foreach (dynamic typeConfiguration in configurations.Value)
{
modelBuilder.Configurations.Add(typeConfiguration);
}
Database.SetInitializer(new CreateTablesIfNotExist<DefaultDbContext>());
}
}
So this way we have a single DbContext for everything.
PROBLEM:
We've run into an issue whereby when we dynamically add new modules (which have their own mappings), then EF does not load those mappings ever, even when we are sure that a new instance of DefaultDbContext has been created. So, it must be that EF is cacheing the mappings somewhere. Is there some way to clear the cache?
FINAL NOTE:
As you may have guessed, we are using an IoC, namely Autofac. If you need any further info, just ask.
Any ideas, anyone?
The model is cached for performance reasons.
The following excerpt explains what is going on
Model Caching
There is some cost involved in discovering the model, processing Data Annotations and applying fluent API configuration. To avoid incurring this cost every time a derived DbContext is instantiated the model is cached during the first initialization. The cached model is then re-used each time the same derived context is constructed in the same AppDomain.
This text also mentions a property called CacheForContextType but this didn't make it into the final release of EF5.
This second link provides a glimmer of hope but again is dated before the final release of EF5
We removed CacheForContextType in CTP5, we originally intended it to be used when folks wanted to use the same context in the same AppDomain with different models. The issue is that it would create the model on every initialization and didn't allow any way to cache a series of models and choose which one to use during each initialization. Model creation is expensive so we wanted to promote a better pattern.
The pattern we recommend is to externally create a ModelBuilder -> DbDatabaseMapping -> DbModel for each model you want to use. The DbModel should be cached and used to create context instances. The ModelBuilder -> DbModel workflow is a little messy and the class names aren't great, they will be tidied up for RTM.
Personally I think you're going to have to find a way of knowing all of your models up front ...
Solved! We found this constructor on the DbContext class:
public DbContext(string nameOrConnectionString, DbCompiledModel model);
I can't share all of the code here, but basically we're creating a new DbCompiledModel and passing that in whenever necessary.

Advice on my ASP.NET MVC, EF layer, and Automapper setup for a project

I'm trying to figure out the best approach to architecting this project. Basically, it's a "band" profile site. I'm using ASP.NET 4, EF, and Automapper (structuremap too, but that's not important). I'm running into performance issues and need advice on whether my approach is right or not (my guess is not). I'll focus on specific sections and provide stripped down examples.
I have a EntityFramework repository class that interacts directly onto the EF objects using LINQ:
[Pluggable("Repository")]
public class EntityDataRepository : IRepository
{
static EntityDataRepository()
{
// other mappings removed
// Data. objects are EF objects, mapping to my DTO classes
Mapper.CreateMap<Data.Event, Models.EventModel>();
Mapper.CreateMap<Data.Genre, Models.GenreModel>();
Mapper.CreateMap<Data.Band, Models.BandModel>();
}
public IEnumerable<BandModel> GetBandsByUser(Guid userId)
{
using (var ctx = new DbContext())
{
var user = GetCurrentUserModel(ctx, userId);
var efBands = from r in user.BandRelations
orderby r.Date
select r.Band;
return Mapper.Map<IEnumerable<Data.Band>, IEnumerable<Models.BandModel>>(efBands);
}
}
}
Bands have genres and events. Note that it maps the EF objects to my DTO object, and returns a list of them. It acts as a proxy to enable my controllers to invoke methods on to obtain the data that it needs (actual logic altered to show what I need):
namespace OpenGrooves.Web.Areas.Edit.Controllers
{
[Authorize]
public class MyBandsController : BaseController
{
public ActionResult ShowBands()
{
IEnumerable<BandModel> bands = repository.GetBandsByUser(loggedUserGuid).First();
return View(bands);
}
}
}
Finally, here's the BandModel class, which is mirroring the Band class entity in EF:
public class BandModel
{
// fluff and scalar properties removed
public IEnumerable<EventModel> Events { get; set; }
public IEnumerable<GenreModel> Genres { get; set; }
}
Basically, am I doing this right? In my EF to DTO classes, the Band EF entity has navigational properties, such as Genres and Events. The problem is, during the mapping that takes place in automapper, these list properties are being populated, especially if one of my proxy methods returns a list of BandModels. It seems to be invoking the Genres and Event EF queries for each record, which is a major performance killer obviously (at least 2 queries for Events and Genres are ran for each BandModel object returned).
Is it OK practice to use EF objects directly in my controllers, possibly even used as models for views?
Is there something I need to change in my mappings to enable lazy loading for these navigational properties (events, genres off a BandModel object)?
Thanks!!
Is it OK practice to use EF objects directly in my controllers, possibly even used as models for views?
Yes, Kinda.
This answer is subjective and depends on how you view your separation of concerns. Most MVC developers, including me, swear on view models. It decouples your data or domain classes from the presentation layer. This is awesome.
Some people don't like being awesome, including other languages and frameworks like every PHP MVC framework, Rails, and Django. Nobody can say these languages "do it wrong" but us .NET devs subscribe to a different paradigm.
Your second question is strange you say "is there something to enable lazy loading" right after you say lazy loading is happening. Care to explain?
Lazy loading is on by default in EF4.

Categories