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.
Related
I'm struggling a little bit with following problem. Let's say I want to manage dependencies in my project, so my domain won't depend on any external stuff - in this problem on repository. In this example let's say my domain is in project.Domain.
To do so I declared interface for my repository in project.Domain, which I implement in project.Infrastructure. Reading DDD Red Book by Vernon I noticed, that he suggests that method for creating new ID for aggregate should be placed in repository like:
public class EntityRepository
{
public EntityId NextIdentity()
{
// create new instance of EntityId
}
}
Inside this EntityId object would be GUID but I want to explicitly model my ID, so that's why I'm not using plain GUIDs. I also know I could skip this problem completely and generate GUID on the database side, but for sake of this argument let's assume that I really want to generate it inside my application.
Right now I'm just thinking - are there any specific reasons for this method to be placed inside repository like Vernon suggests or I could implement identity creation for example inside entity itself like
public class Entity
{
public static EntityId NextIdentity()
{
// create new instance of EntityId
}
}
You could place it in the repository as Vernon says, but another idea would be to place a factory inside the constructor of your base entity that creates the identifier. In this way you have identifiers before you even interact with repositories and you could define implementation per your ID generation strategy. Repository could include a connection to something, like a web service or a database which can be costly and unavailable.
There are good strategies (especially with GUID) that allow good handling of identifiers. This also makes your application fully independent of the outside world.
This also enables you to have different identifier types throughout your application if the need arises.
For eg.
public abstract class Entity<TKey>
{
public TKey Id { get; }
protected Entity() { }
protected Entity(IIdentityFactory<TKey> identityFactory)
{
if (identityFactory == null)
throw new ArgumentNullException(nameof(identityFactory));
Id = identityFactory.CreateIdentity();
}
}
Yes, you could bypass the call to the repository and just generate the identity on the Entity. The problem, however, is that you've broken the core idea behind the repository: keeping everything related to entity storage isolated from the entity itself.
I would say keep the NextIdentity method in the respository, and still use it, even if you are only generating the GUID's client-side. The benefit is that in some future where you want to change how the identity's are being seeded, you can support that through the repository. Whereas, if you go with the approach directly on the Entity, then you would have to refactor later to support such a change.
Also, consider scenarios where you would use different repositories in such cases like testing. ie. you might want to generate two identities with the same ID and perform clash testing or "does this fail properly". Having a repository handle the generation gives you opportunity to get creative in such ways, without making completely unique test cases that don't mimic what actual production calls would occur.
TLDR; Keep it in the repository, even if your identifier can be client-side generated.
I'm porting old VB6 code (yes yes, VB6...) to C#. I'm refactoring code to be more object-oriented, and among other things, I'm implementing repository classes to access the database.
Now, these repository classes return objects, not datasets. But I find that sometimes I only return a subset of the information an object might hold. Example: I can get a complete list of documents, with name, filepath, folder, creator, etc - or I can get document search results which only contain name and folder.
What is the best practice for these subset cases? Should I create custom objects for these database calls, that only contain the subset of data? Should I return the complete objects with only some of their fields populated? Or should I just return datasets?
Ideally, everything should be centralized as much as possible. This could be done by creating a query object for each subset. I think you can go either way with returning objects with some fields populated or null, dependent if your database allows nulls for those specific fields.
So centralize your rules and logic with your repository classes so that each object is returned consistently based on those rules and logic.
Create an underling schema for your objects so they do not get too complex. I think what is need is an entity per object to be consider for repository. Again, creating custom objects or DTO's could create unneeded code and complexity. For the sake of integrity, keep your objects with some fields populated and others that are not needed within that subset null, that way if this information is queried later, information can be reported back that value does not exist for a specific entity.
Here is a brief example, try using POCO classes with the entity framework.
public interface IRepository<TEntity, in TKey> where TEntity : class
{
TEntity Get(TKey id);
}
public class SomeRepo1 : IRepository
{
private readonly FileDbContext someDbContext;
public FileRepository(FileDbContext dbContext)
{
someDbContext = dbContext;
}
public File Get(string id)
{
return someDbContext.Files.ToList();
}
}
Example of POCO Class that can be used for files:
public class File
{
public int Id { get; set; }
public string FileName { get; set; }
}
public class Folder
{
public List<File> Files { get; set; }
}
More details here: https://msdn.microsoft.com/en-us/library/ff649690.aspx
Hope this helps!
But I find that sometimes I only return a subset of the information an object might hold.
You have just confused the object model with the persistence model.
You see, the object model doesn't care how the storage is implemented. Specifically, if there is a database behind the object model and you have tables that contain some data, you are free to map the database to your object model in any way you want. With a clever object-relational mapper you can for example split a table into two classes or have multiple classes persisted in the same table.
So, something that looks like "a subset" from the perspective of your storage, could possibly not be "a subset" from the object-model perspective.
An example specific Entity Framework 6 solution involves so called Table Splitting which allows you to split a model class into two classes, a class with core properties that are always loaded and another class with auxiliary properties that are lazily loaded only when you refer to the virtual property of the core class.
An example tutorial: http://www.c-sharpcorner.com/UploadFile/ff2f08/table-splitting-in-entity-framework-6-code-first-approach/
(just to mention, the opposite, where two physical tables are mapped to oe model class is called Entity splitting)
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.
Let's say I have 'Customer' table in SQL DB and I'm using Entity Framework.
Now, for instance, in Controller or ViewModel I retrieve the customer by var customer = Page.Current.Customer when it's code is:
public class Page
{
...
// Customer is EntityObject that created by Entity Framework
public Customer Customer
{
get
{
return (new ContextEntity()).Customers.First();
}
}
}
My question:
Should I refer to Entity Object class(Customer) as DAL and create CustomerWrapper or I can use it in other code of my application?
I mean, is it correct that Page.Current.Customer will return Customer Entity or I should use Customer Entity as DAL and Page.Current.Customer should return custom Customer, some kind of CustomWrapper?
In one hand if will decided to change Customer table name to site_Customer(in SQL DB) I'll refresh the EntityModel and will only change the code in the Page class to
public class Page
{
...
// Customer is EntityObject that created by Entity Framework
public Customer Customer
{
get
{
return (new ContextEntity()).site_Customers.First();
}
}
}
But in the other hand I'll have Customer Entity + WrapperCustomer
What is better?
All class in an EDMX file are partial classes. This means that you can extend these classes by creating a new Class file.
For example...
public partial class Customer
{
// Here are the methods, properties, relationships created by EDMX Wizard.
}
In another area of your project, I usually put it in the same location as the EDMX, you can add a new Class file that has the same signature.
public partial class Customer
{
// Here are the methods, properties, etc. created by you.
}
When the project is compiled these two classes will become one class in the compiled code. Now, when you change your EDMX, yes it should map correctly, but this is not always the case as EF has be known to be very buggy (suppose to be fixed with EF 4.1 in MVC 3), you can simply change the class name to match whatever it is in the EDMX and "Voila!" you have transferred all custom added code for the class to the new entity object. This is essentially your "class wrapper".
That all depends on the level of abstraction you want to use in your application and needs of presentation layer. Both approaches are possible.
Your code is probably already tightly coupled to Entity Framework (EntityObject is EF type) and it is also not very well testable (Page.Current is probably static) so discussion about some more advanced architecture approaches and separation of concerns is not needed.
Few observations from your code:
Context is Disposable!!!
Renaming anything in your database should not modify your class names. That is the responsibility of EF mapping (EDMX) to correctly map entities to new database names.
If you want to use WCF, then you will probably need to create clear POCOs to avoid a lot of issues.
If you want your controllers/viewmodels/pages/whatever to be unit testable, then you will need to abstract your EntityContext in repository interfaces+classes (see repository pattern).
If you just want to make a quick and simple non-testable application, then you don't need to bother about it. Don't forget to dispose the data context at the end of each request.
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.