Ardalis CleanArchitecture - BaseEntity & Composite Keys for AggregateRoots - ardalis-cleanarchitecture

What is the recommendation for extending BaseEntity as an AggregateRoot is I need to have a composite Key?
Essentially I need to be able to manage an Entity that would normally be configured in EFCore like:
builder.HasKey(z => new { z.PartA, z.PartB });
Currently the template gives us the following definition of BaseEntity, but it's unclear to me how I might need to setup the EntityTypeCuilder config, and how the Aggregates might handle this scenario under the hood.
// This can be modified to BaseEntity<TId> to support multiple key types (e.g. Guid)
public abstract class BaseEntity
{
public int Id { get; set; }
public List<BaseDomainEvent> Events = new List<BaseDomainEvent>();
}
Paul

Related

No key defined. Define the key for this EntityType when implementing interface that has Id

I want to implement an interface defined in Dev Express IResource in my EF Code First business object.
public class JResource : IResource , IXafEntityObject
{
[Key]
public int IdKey { get; set; }
[NotMapped]
public object Id => IdKey; // since IResource wants this.
// other properties
}
When I run my application to create the database I get an error that I need to define the key for this EntityType.
I think the problem is that EF wants to regard Id as the Key but I have made Id NotMapped since I want it to be an Int and the interface wants it to be an object.
Is there a work around?
It turned out that I was using the wrong reference for the [Key] attribute.
The correct one is
System.ComponentModel.DataAnnotations.KeyAttribute

Including Identity User with Entity Framework doesn't work

I am having trouble including my Identity User in query results. Other entities are included just fine, no matter how many levels deep.
Here's the model I'm using.
Building * --- 1 City
* *
| /
| /
1 1
ApplicationUser
And the context:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public DbSet<City> Cities { get; set; }
public DbSet<Building> Buildings { get; set; }
}
Both Building and City have these properties:
public Guid ApplicationUserId { get; set; }
public virtual ApplicationUser ApplicationUser { get; set; }
The query I'm using to retrieve data:
var building = context.Buildings
.Include(c => c.ApplicationUser)
.Include(c => c.City)
.Include(c => c.City.ApplicationUser)
.First();
In the result City is populated just fine, however ApplicationUser is not.
Could this be a naming issue? I've already tried UserId / User and AspNetUserId / AspNetUser as property names without succes.
I'm using Migrations to create the database. The table name that gets created for users is AspNetUsers.
I'm using entity framework 7 beta 7, not sure if this applies to other versions as well.
These are the files generated by EF Migrations.
ApplicationDbContextModelSnapshot.cs
20150929181902_Init.cs
20150929181902_Init.Designer.cs
(I noticed I forgot to include the Building > City relation when generating files for upload, but that shouldn't matter for the example)
I've finally figured it out.
ApplicationUser inherits from IdentityUser which inherits from IdentityUser<string>. The generic type is used as the primary key, so a string!
I changed my Guid foreign key properties to strings and now everything is working.
Just to help anyone who also have a similar issue. I was facing same thing, same scenario: My custom identity user has some related entities and using .Include was not working. None of them would come back. But they used to.
Turns out I had created a custom ApplicationUserStore to automatically include the entities I would normally always need when retrieving a User but I had only overridden FindByIdAsync method. When I tried to use FindByNameAsync no entity would come back, obviously. Just had to override this and the other Find methods.

How to organize a project into three tiers?

I have an asp.net website and I would like to organize it into three layers
DataAccess
Domain
UI
What specifically goes in each of these layers?
e.g
Data
- Models
- Repositories? Would that be just interfaces
- IoC?
Domain
- Services?
UI
- javascript
- Area specific models?
- css
Could someone provide a simple guideline for organizing an asp.net website like this?
As other people have said each situation is different, but for a basic architecture, I would probably go along with something like this. It has gotten me out of a few jams and up and running quite quickly.
Infrastructure Layer
This is where all the data access is done. Database connection management, etc.
The Repositories include all queries to the database.
The Dependency Resolution sits here too. Use your DI Container of choice.
Domain Layer
This is where all you business logic sits.
The Domain Services Interfaces are what the UI layer call to use your business logic
UI
Pretty obvious this one....
Code Example
--UI
public class MyController
{
private readonly IMySerivce _myService;
public MyController(IMySerivce myService)
{
_mySerivce = myService;
}
public void MyAction()
{
_myService.DoSomeAction();
}
}
--Domain
public Interface IMyService()
{
void DoSomeAction();
}
public class MySerivce : IMyService()
{
private readonly IMyRepository _myRespository;
public MySerivce(IMyRepository myRepository)
{
_myRepository = myRepository;
}
public void DoSomeAction()
{
_myRepository.Save();
}
}
public interface IMyRepository
{
void Save();
}
--DataLayer
public MyRepository : IMyRepository
{
public void Save()
{
//Manage Save here
}
}
Additionally I usually have a separate area for unit/integration tests.
Update
This most definitely is dependent on your situation. It is very hard to say what method is best without fully understanding what you are ultimately trying to build.
From the list below you can see which method works well for you or fits well with your architecture.
Regardless of which one you choose, your Repository Implementation will have to have a dependency on your Domain Objects project.
Some techniques in doing it include:
No Mapping
Your Domain Objects really then become dummy mappings to your tables. i.e. have a table in your database call User. Then have a Domain Object called User. This is by far the simplest technique.
--Domain
public class User
{
public int Id {get; set;}
public string UserName {get; set;}
public string FirstName {get; set;}
public string LastName {get; set;}
public string Password {get; set;}
}
--Infrastructure
public class UserRepository : IUserRepository
{
public Core.User GetById(int id)
{
return DBConnection.GetByIdQuery(id);
}
}
Mapping
Martin Fowler describes it here
It is possible in your infrastructure layer to have what are known as Domain Transfer Objects (DTO) that represent your database tables. Similar to above, a table called User, a DTO called User. Both having the same properties.
Your domain Entity then becomes a true representation of your domain and business logic.
The mapping of the DTO to your Domain Entity (search query) can be done in the Repository and the mapping of your Domain Entity to your DTO (save/update query) would also be done in your Repository.
To do your mapping you can either create custom mapping classes or use 3rd party tools like AutoMapper. I am a big fan of AutoMapper.
A sample code example would be along the lines of:
--Custom mapper
public class UserRepository : IUserRepository
{
private readonly IUserMapper _userMapper;
public UserRepository(IUserMapper userMapper)
{
_userMapper = userMapper;
}
public Domain.User GetUserById(int id)
{
var DtoUser = GetUserByIdQuery(int id);
return _userMapper.MapUserDTOToDomainEntity(DtoUser);
}
}
public class UserMapper : IUserMapper
{
public Domain.User MapUserDTOToDomainEntity(DataEntity.User dtoUser)
{
//Manual property mapping
}
}
--AutoMapper Example
public class UserRepository : IUserRepository
{
public Domain.User GetUserById(int id)
{
var DtoUser = GetUserByIdQuery(int id);
return Mapper.Map<Domain.User>(DtoUser);
}
}
Other examples include:
https://stackoverflow.com/questions/14724612
There are many many debates out there in blogs and here on SO about the value of DTO's,
including MSDN, this blog and these https://stackoverflow.com/questions/11237946, https://stackoverflow.com/questions/15148866

Entity Framework & RIA Services - CRUD on Link Table

After many hours, countless failures, I decided to change my Entity Model to include a link table in the model for each many-to-many relationship. This worked for me because RIA Services doesn't support many-to-many relationships.
Regardless, I'm able to build, but do not have any idea how to manage these relationships within the application itself. Should I create methods on the Domain Service, that are hidden from the client and used to perform CRUD operations on the link table objects?
An example would be greatly appreciated, thanks in advance.
I guess you already know http://m2m4ria.codeplex.com/ that adds many to many support to wcf ria services, however if you want to manage it by yourself, you better send it to the client and treat them like any other entities. You will not have Entity A with a collection of B entities and entities B with a collection of A entitities but rather:
public class A
{
int Id {get; set;}
ICollection<A_To_B> B_Entities {get; private set;}
}
public class A_To_B
{
int Id {get; set;}
A EntityA {get; set;}
int id_A {get; set;}
B EntityB {get; set;}
int id_B {get; set;}
}
public class B
{
int Id {get; set;}
ICollection<A_To_B> A_Entities {get; private set;}
}
in your domain service add methods to correctly expose all of these entities and don't forget to properly decorate them (relationship is straight 1:m)
This is indeed a nuisance.
I've not tried m2m4ria and do it manually on the client, ie. I expose the bridge table in the domain service. Sometimes it turns out to be a good idea anyway if the bridge table is later elevated to carry more data.
To ease the pain of managing the bridge table on the client I've written some helper you might want to consider yourself.
public interface ILinkEntity
where LinkEntity : Entity, ILinkEntity
where SourceEntity : Entity, ILinkedSourceEntity
where TargetEntity : Entity
{
SourceEntity Source { get; set; }
TargetEntity Target { get; set; }
}
public interface ILinkedSourceEntity
where SourceEntity : Entity, ILinkedSourceEntity
where LinkEntity : Entity, ILinkEntity
where TargetEntity : Entity
{
EntityCollection Links { get; }
ObservableCollection Targets { get; set; }
}
public static class ManyToManyHelper
{
public static void UpdateLinks(this ILinkedSourceEntity source, EntitySet set)
where SourceEntity : Entity, ILinkedSourceEntity
where LinkEntity : Entity, ILinkEntity, new()
where TargetEntity : Entity
{
if (!(source is SourceEntity)) throw new Exception("Expected source to be a SourceEntity.");
var toAdd = (
from target in source.Targets
where source.Links.FirstOrDefault(le => le.Target.Equals(target)) == null
select target
).ToArray();
foreach (var target in toAdd) source.Links.Add(new LinkEntity() { Source = source as SourceEntity, Target = target });
var toRemove = (
from link in source.Links
where source.Targets.FirstOrDefault(te => te.Equals(link.Target)) == null
select link
).ToArray();
foreach (var link in toRemove)
{
source.Links.Remove(link);
// This can happen when the entities had not yet been added to the context.
set.Remove(link);
}
}
public static void UpdateTargets(this ILinkedSourceEntity source)
where SourceEntity : Entity, ILinkedSourceEntity
where LinkEntity : Entity, ILinkEntity, new()
where TargetEntity : Entity
{
if (source.Targets == null)
{
source.Targets = new ObservableCollection();
}
else
{
source.Targets.Clear();
}
foreach (var link in source.Links) source.Targets.Add(link.Target);
}
}
I have this in a file called ManyToManyUtils and it should live somewhere where your domain entities can reference them (so typically in the domain client project).
I then augment the respective auto-generated domain entities to support those interfaces, eg. like this:
public partial class Question : ILinkedSourceEntity
{
EntityCollection ILinkedSourceEntity.Links
{
get { return QuestionCategories; }
}
public ObservableCollection Categories { get; set; }
ObservableCollection ILinkedSourceEntity.Targets
{
get { return Categories; }
set { Categories = value; }
}
}
public partial class QuestionCategory : ILinkEntity
{
Question ILinkEntity.Source { get { return Question; } set { Question = value; } }
Category ILinkEntity.Target { get { return Category; } set { Category = value; } }
}
public partial class Category
{
}
So in this example each Question can be in many categories. Category as a domain entity needs not to be modified.
I usually augment domain entity classes with properties frequently anyway, so I often already have those partial classes.
Now I can bind views against those new collection properties. However, I still need to call the helper update methods to sync the bridge table with those helper collection properties.
So after each load or refresh from the domain services you have to call:
myQuestion.UpdateTargets();
And after each edit by the user (eg from a SelectionChanged handler in the view, or - if you are happy with the consequences - just before you call SaveChanges), call:
myQuestion.UpdateLinks(myContext.QuestionCategories);
That way, the nastiness is factored out as much as possible.

EF Code First - Fluent API (WithRequiredDependent and WithRequiredPrincipal)

I have the following class:
public class User
{
public Guid Id { get; set; }
public string Name { get; set; }
public Couple Couple { get; set; }
}
public class Couple
{
public Guid Id { get; set; }
public User Groom { get; set; }
public User Bride { get; set; }
}
Important points:
Bride and Groom properties are required
One-to-one relationship
In the User class, it is Couple required
DbContext in OnModelCreating
modelBuilder.Entity<User>().HasRequired(u => u.Couple).WithRequiredPrincipal();
modelBuilder.Entity<Couple>().HasRequired(u => u.Bride).WithRequiredDependent();
modelBuilder.Entity<Couple>().HasRequired(u => u.Groom).WithRequiredDependent();
But I can not be required!
All fileds are with null in the database!.
How do I get the fields in the database as not null?
If possible using the API Flient.
It should be this :
modelBuilder.Entity<User>().HasRequired(u => u.Couple).WithRequiredDependent();
modelBuilder.Entity<Couple>().HasRequired(u => u.Bride).WithRequiredDependent();
modelBuilder.Entity<Couple>().HasRequired(u => u.Groom).WithRequiredDependent();
How WithRequiredDependent Works : Configures the relationship to be required:required without a navigation property on the other side of the relationship. The entity type being configured will be the dependent and contain a foreign key to the principal. The entity
type that the relationship targets will be the principal in the relationship.
Meaning : Let's consider your first line of code here. It creates a foreign key in the entity being configured (User) making it Dependant and making the other side of the relationship (Couple) Principal
Important : Don't you think the configuration you desire will generate a deadlock? I've not tested the code above, but this configuration seems to be a deadlock to me so i'm not sure if EF would allow you to create it. User must need a Couple, and Couple must need that same user i guess.

Resources