I'm using EF 4.1 code first. Given the following class snippet:
public class Doctor
{
public virtual ICollection<Hospital> Hospitals { get; set; }
}
Note: I have this in the database context:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
this.Configuration.LazyLoadingEnabled = false;
}
I wanted to make sure that lazy loading is not involved here.
The issue I have is that, without the virtual keyword on the Hospitals property, when I retrieve a doctor that does have a hospital associated with him, the collection is empty.
By including the virtual keyword, the hospitals collection does contain 1 item, which is what I expect.
The problem is that, when I want to create a brand new doctor and associate him with a hospital immediately, I get a Null reference exception, since the Hospitals property has not been initialised yet.
Can someone point out what I'm doing wrong here? How can I add items to the Hospitals upon creating a new doctor.
Cheers.
Jas.
Your code is something what you usually see in all examples but to make this work this one is much better:
public class Doctor
{
private ICollection<Hospital> _hospitals;
public virtual ICollection<Hospital> Hospitals
{
get { return _hospitals ?? (_hospitals = new HashSet<Hospital>()); }
set { _hospitals = value }
}
}
If you don't use virtual keyword EF will not initialize collection for you. In the same time if you create brand new Doctor via its constructor you must handle initialization yourselves.
I think this can help you.
public class Doctor
{
public Doctor()
{
Hospitals = new ICollection<Hospital>();
}
public virtual ICollection<Hospital> Hospitals { get; set; }
}
Related
I'm working on a new project that uses CosmosDB and Entity Framework Core (via the Microsoft.EntityFrameworkCore.Cosmos NuGet package, version 5.0.7; the project itself is .NET Core 5). I'm new to both, and running into an issue I can't sort out.
In short, I need to save a complex object to the database. It's a big model that will have multiple collections of classes underneath it, each with their own properties and some with collections underneath them as well. I'm trying to configure EF with OwnsOne and OwnsMany to store these child objects underneath the top-level one. The code compiles, and will save to the database so long as all the owned objects are left empty. But whenever I put anything into an owned object, either with OwnsOne or OwnsMany, I get a pair of NullReferenceExceptions.
I've tried to strip my code down to the very basics. Here's how it currently looks.
Owner and owned classes:
public class Questionnaire
{
// Constructors
private Questionnaire() { }
public Questionnaire(Guid id)
{
Test = "Test property.";
TV = new TestQ();
Id = id;
}
public Guid Id { get; set; }
public string Test { get; set; }
public TestQ TV { get; set; }
// Public Methods
public void AddForm(Form f)
{
// not currently using this method
//Forms.Add(f);
}
}
public class TestQ
{
public TestQ()
{
TestValue = "test ownsone value";
}
public string TestValue { get; set; }
}
DbContext:
public class QuestionnaireDbContext : DbContext
{
public DbSet<Questionnaire> Questionnaires { get; set; }
public QuestionnaireDbContext(DbContextOptions<QuestionnaireDbContext> options) : base(options) { }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.HasDefaultContainer(nameof(Questionnaires));
modelBuilder.Entity<Questionnaire>().HasKey(q => q.Id);
modelBuilder.Entity<Questionnaire>().OwnsOne(q => q.TV);
}
}
And the code from the service that calls the dbContext (note that this is based on a generic service that I didn't set up originally). The actual exceptions are thrown here.
public virtual TEntity Add(TEntity entity)
{
_context.Entry(entity).State = EntityState.Added;
_context.SaveChanges();
return entity;
}
Ultimately I need this to work with OwnsMany and a collection, but I figured it might be simpler to get it working with OwnsOne first. The key thing to note here is that if I comment out the line
TV = new TestQ();
in the Questionnaire class, the model persists correctly into CosmosDB. It's only when I actually instantiate an owned entity that I get the NullReferenceExceptions.
Any advice would be much appreciated! Thank you!
Well, I'm not sure why this is the case, but the issue turned out to be with how we were adding the document. Using this generic code:
public virtual async Task<TEntity> Add(TEntity entity)
{
_context.Entry(entity).State = EntityState.Added;
await _context.SaveChanges();
return entity;
}
was the issue. It works just fine if I use the actual QuestionnaireDbContext class like so:
context.Add(questionnaire);
await context.SaveChangesAsync();
I know that keeping large collections in Aggregates impacts performance.
In my use case i have STORE which can have multiple PRODUCT and each product can have CUSTOMIZATION(Not more than 10-20 customization).
I thought of creating one store aggregate only and update product and customization through it but as product collection can be large so it will impact performance. So I have two aggregates STORE(to create store) and PRODUCT(with storeId,all product operation) with this approach I am not able to check if product already exist or not.
what i am doing now is getting all products by StoreId in my handler and checking duplicate which is not right way as it should belong to my domain model.
Anyone has better idea to solve this.
below are my domain models.
public class Store : Entity<Guid>, IAggregateRoot
{
private Store()
{
this.Products = new List<Product>();
}
private Store(string name, Address address) : base(System.Guid.NewGuid())
{
this.Name = name;
this.Address = address;
}
private Store(string name, Address address, ContactInfo contact) : this(name, address)
{
this.Contact = contact;
}
public string Name { get; private set; }
public Address Address { get; private set; }
public ContactInfo Contact { get; private set; }
}
public class Product : Entity<Guid>, IAggregateRoot
{
private Product()
{
}
private Product(Guid storeId, ProductInfo productInfo) : base(Guid.NewGuid())
{
this.ProductInfo = productInfo;
this.StoreId = storeId;
this.Customizations = new List<Customization>();
}
private Product(Guid storeId, ProductInfo productInfo, IEnumerable<Customization> customizations) : this(storeId, productInfo)
{
this.Customizations = customizations;
}
public ProductInfo ProductInfo { get; private set; }
private List<Customization> _customizations;
public IEnumerable<Customization> Customizations
{
get
{
return _customizations.AsReadOnly();
}
private set
{
_customizations = (List<Customization>)value;
}
}
public Guid StoreId { get; private set; }
public static Product Create(Guid storeId, ProductInfo productInfo)
{
return new Product(storeId, productInfo);
}
public void UpdateInfo(ProductInfo productInfo)
{
this.ProductInfo = productInfo;
}
public void AddCustomization(Customization customization)
{
this._customizations.Add(customization);
}
public void RemoveCustomization(Customization customization)
{
this._customizations.Remove(customization);
}
}
Well as correctly Jonatan Dragon mentioned and you found the solution in an article of course you can use domain services but taking this approach for solving these kind of problems has the danger to fall in the anemic domain model pitfalls in future developments. This is the most common cause of loosing technical excellency in the domain layer. In general whenever a problem must be solved with objects collaborations, this kind of problems will be occurred. Therefore whenever is possible to avoid using domain services it's better to find the other answers that doesn't utilize this pattern. For your case the problem can be solved without using domain services by working around on some trade-offs to handle non-functional issues (like performance) and keeping the models rich and clean!
Let's consider some assumptions for designing aggregates to identify where do we want to involve trade-offs which we will accept for solving this problem:
1- In designing aggregates, just one aggregate's state must changes during one transactional use-case. (Greg Young)
2- In designing aggregates, the things can be shared among aggregates are only their IDs. (Eric Evans)
It seems these two assumptions make our minds enclosed in a frame that solve this kind of problems by only utilizing domain services. So let's look at them more deeply.
Many DDD practitioners and mentors like Nick Tune knows the transaction default scope over the entire BC in a use-case instead of only consider it for one aggregate. Therefor this is the place where we have some degrees of freedom to involve with trade-offs.
For number 2, the philosophy behind this assumption is to share only the part of aggregates that it's invariant and never modifies during the aggregate's lifespan. Therefor not so many aggregates get locked during a transaction in one use-case. Well if there's case that a shared state of aggregates changes on one transaction scope and there's no way for that to modify separately, technically there will be no problem in sharing it.
By mixing these two we can conclude to this answer for this problem:
You can let the Store aggregate to decide for creating a Product aggregate. In OOP words you can make The Store aggregate be the Product aggregate Factory.
public class Store : Entity<Guid>, IAggregateRoot
{
private Store()
{
this.Products = new List<Product>();
}
private Store(string name, Address address) : base(System.Guid.NewGuid())
{
this.Name = name;
this.Address = address;
}
private Store(string name, Address address, ContactInfo contact) : this(name, address)
{
this.Contact = contact;
}
public Product CreateProduct(Guid storeId, ProductInfo productInfo)
{
if(ProductInfos.Contains(productInfo))
{
throw new ProductExistsException(productInfo);
}
this.ProductInfos.Add(productInfo);
return new Product(storeId, productInfo);
}
public string Name { get; private set; }
public Address Address { get; private set; }
public ContactInfo Contact { get; private set; }
public List<ProductInfo> ProductInfos {get; private set;} = new();
}
In this solution i considered ProductInfo as a value object, hence checking duplication can easily be done by checking their equality. For ensuring the Product aggregate can not be constructed independently you can make it's ctor's access modifier as internal. Usually aggregate models placed in one assembly and ORMs can use non public ctors too, therefor this will create no problem.
There are some points to notice in this answer:
1- The Store aggregate must not use the internal parts of ProductInfo. With this approach ProductInfo can change freely as it's owner ship belongs to Product aggregate.
2- As ProductInfo is a value object, storing and recovering the Store aggregate is not a heavy operation and by converting techniques in ORMs this can reduce to storing and recovering data from only one field for ProductInfos collection.
3- The Store and the Product aggregates are only coupled for Product creation use-case. They can operate freely separate in other use-cases.
So with this approach you will achieve small aggregate separation in 99% of use-cases and the duplicate checking as the domain model invariant.
PS: This is the core idea of how to solve the problem. You can cook it with other patterns and techniques like Explicit State Pattern and Row Versions if it's required.
At first make sure it really impacts the performance. If you really need 2 aggregates, you can use a Domain Service to solve your problem. Check this article by Kamil Grzybek, section BC scope validation implementation.
public interface IProductUniquenessChecker
{
bool IsUnique(Product product);
}
// Product constructor
public Product(Guid storeId, ProductInfo productInfo, IProductUniquenessChecker productUniquenessChecker)
{
if (!productUniquenessChecker.IsUnique(this))
{
throw new BusinessRuleValidationException("Product already exists.");
}
...
}
My current employer is developing a mobile app using Xamarin.Forms and Asp.net mvc on the backend. I suggested to use realm in the mobile app. My manager want to see a POC(Proof of concept) app using realm with backlink feature before allowing it to be used in the app. I am working on the POC on GitHub . The documentation is very limiting and the GitHub repo of realm-dotnet don’t have good sample.
I completed the project. But unable to implement backlink. The sample app I have developed allow user to create assignees(employees) in the first page. The user can delete or edit the employees using context menu. When the user clicks on the employee name the app navigates to the ToDoListPage of that particular employee. Here the user can create ToDoItems. On this ToDoList page I want to show the ToDoItems that where assigned to that employee only.
The models were as follows:
public class Assignee : RealmObject
{
public Assignee()
{
ToDoItems = Enumerable.Empty<ToDoItem>().AsQueryable();
}
[PrimaryKey]
public string Id { get; set; } = Guid.NewGuid().ToString();
public string Name { get; set; }
public string Role { get; set; }
[Backlink(nameof(ToDoItem.Employee))]
public IQueryable<ToDoItem> ToDoItems { get; }
}
public class ToDoItem : RealmObject
{
[PrimaryKey]
public string Id { get; set; } = Guid.NewGuid().ToString();
public string Name { get; set; }
public string Description { get; set; }
public bool Done { get; set; }
public Assignee Employee { get; set; }
}
I am adding employee to each ToDo Item:
Item.Employee = Employee;
_realm.Add(Item);
Now I want to access the ToDoItems for the Employee:
Items = _realm.All<Assignee>().Where(x => x.Id == EmployeeId).FirstOrDefault().ToDoItems;
But this does not work. I will be grateful if someone can help me out by preferably writing code in my sample app or write the correct code in the reply.
Thank you
Firstly, Realm .NET doesn't currently support traversing properties (x.Employee.Id). Due to this, when I start the app and try to go to the ToDoListPage, the app crashes with the exception:
The left-hand side of the Equal operator must be a direct access to a persisted property in Realm
Realm supports object comparison, so we can fix this like so:
var employee = _realm.Find<Assignee>(EmployeeId);
Items = _realm.All<ToDoItem>().Where(x => x.Employee == employee);
Secondly, everything seemed fine in your code, so I dug a bit deeper and saw why it isn't working. The issue is that when we try to get all items with the code above, the EmployeeId parameter is null. Since the EmployeeId is being populated after the load logic has been triggered, we don't need to load the data in the ctor. So you can remove this code.
Finally, since you won't be loading the data in the ctor, and instead in the SetValues method, the UI needs to know, when the data has been updated, what exactly to redraw. Thus, you need to mark the collection to be Reactive too:
[Reactive]
public IEnumerable<ToDoItem> Items { get; set; }
Then, you need to change the SetValues method to use object comparison, instead of traversing:
async Task SetValues()
{
Employee = _realm.Find<Assignee>(EmployeeId);
Title = Employee.Name;
Items = _realm.All<ToDoItem>().Where(x => x.Employee == Employee);
}
To sum up - you don't need to try and load the data in the ctor, since you don't know when the EmployeeId will be set. You are already tracking when the property will change and inside the SetValues command you simply need to change the expression predicate.
public class Standard
{
public Standard()
{
Students = new List<Student>();
}
public int StandardId { get; set; }
public string Description { get; set; }
public virtual ICollection<Student> Students { get; set; }
}
What is the purpose of construting Students = new List<Student>(); above for EF code first?
You certainly don't have to initialize Students in the constructor. There are also other patterns. Note that it's entirely possible to construct an object without the constructor ever running (for example, some serializers work that way), so this may not even work in all cases.
Until you initialize Students, it will be null. If you try Students.Add(myStudent) somewhere in your code before any initialization happens, you will get a NullReferenceException.
Another common pattern is to perform a lazy initialization of the Students property, e.g.
private List<Student> students;
public List<Student> Students
{
get
{
if (students == null) students = new List<Student>();
return students;
}
set { students = value; }
}
This pattern can be helpful if an object might be constructed without the constructor running, but also has its own set of pitfalls (for example, as written it is not thread safe).
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