I use EntityFramewotk and code first approach. So, I describe my model like this:
class Person
{
public long Id { get;set; }
public string Name { get;set; }
public ICollection<Person> Parents { get;set; }
}
But, my domain logic don't allow to modify Parents collection (add, delete), it must be readonly (just for example). EntityFramework requires all Collections have ICollection<T>
interface, and it has Add
method (to materialize results) and Remove
method, and others.
I can create my own collection with explicit implementation of interface:
public class ParentsCollection : ICollection<Person>
{
private readonly HashSet<Person> _collection = new HashSet<Person>();
void ICollection<Person>.Add(Person item)
{
_collection.Add(item);
}
bool ICollection<Person>.Remove(Person item)
{
return _collection.Remove(item);
}
//...and others
}
This hides Add
and Remove
methods, but does not protect at all. Because I can always cast to ICollection and call prohibited method.
So, my question is:
Entity Framework Classic Include The Include method lets you add related entities to the query result. In EF Classic, the Include method no longer returns an IQueryable but instead an IncludeDbQuery that allows you to chain multiple related objects to the query result by using the AlsoInclude and ThenInclude methods.
Entity Framework (EF) is an object-relational mapper that enables . NET developers to work with relational data using domain-specific objects. It eliminates the need for most of the data-access code that developers usually need to write. Get it: Add this to your project and start taking advantage of this powerful O/RM.
ReadOnlyCollection makes an array or List read-only. With this type from System. Collections. ObjectModel, we provide a collection of elements that cannot be changed.
Entity Framework (EF) Core is a lightweight, extensible, open source and cross-platform version of the popular Entity Framework data access technology. EF Core can serve as an object-relational mapper (O/RM), which: Enables . NET developers to work with a database using .
In EF Core, you can encapsulate collections and achieve true domain modeling by using backing fields. So, you can define your collection as a private field and expose it as a public readonly property like below as _parents and Parents.
class Person
{
public long Id { get;set; }
public string Name { get;set; }
private List<Person> _parents = new List<Person>();
public IReadOnlyCollection<Person> Parents => _parents.AsReadOnly();
public void AddParent(Parent parent){
_parents.Add(parent);
}
}
As you can see, Parents is a read-only collection and consumers are not allowed to modify it.
Note that _parents is discovered as a backing-field by ef core's convention.
You can expose private collection properties to EF, allowing for mapping and querying, while still keeping your domain object's members and relationships properly encapsulated. It's a bit messy, but it works:
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
public IEnumerable<Order> Orders
{
get { return _orders.AsEnumerable(); }
}
private List<Order> _orders { get; set; }
public Customer()
{
_orders = new List<Order>();
}
public static Expression<Func<Customer, ICollection<Order>>> OrderMapping
{
get { return c => c._orders; }
}
}
Mapping then uses:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Customer>().HasMany(Customer.OrderMapping);
}
This approach is described further here: http://ardalis.com/exposing-private-collection-properties-to-entity-framework
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With