EF Eager Loading Includes Duplicate Entities - c#

I have a User entity and Role entity in a many-to-many relationship. They are injected with Repository instances to be able do lazy loading after the DbContext has been disposed (i.e. outside the Repository layer) like so:
public class User
{
public int UserId { get; set; }
public string UserName { get; set; }
// Lazy loaded property
public ICollection<Role> Roles
{
get { return _roles ?? (_roles = Repository.GetRolesByUserId(UserId)); }
set { _roles = value; }
}
private ICollection<Role> _roles;
public IRepository Repository { private get; set; }
}
public class Role
{
public int RoleId { get; set; }
public string Name { get; set; }
// Lazy loaded property
public ICollection<User> Users
{
get { return _users ?? (_users = Repository.GetUsersByRoleId(RoleId)); }
set { _users = value; }
}
private ICollection<User> _users;
public IRepository Repository { private get; set; }
}
public class Repository : IRepository
{
public ICollection<User> GetAllUsers()
{
using (var db = CreateContext())
{
// Using 'Include' to eager load the Roles collection for each User
return db.Users.Include(u => u.Roles).ToList();
}
}
public ICollection<Role> GetRolesByUserId(int userId)
{
using (var db = CreateContext())
{
return db.Roles.Where(r => r.Users.Any(u => u.UserId == userId))
.ToList();
}
}
public ICollection<User> GetUsersByRoleId(int roleId)
{
using (var db = CreateContext())
{
return db.Users.Where(u => u.Roles.Any(r => r.RoleId == roleId))
.ToList();
}
}
private CustomContext CreateContext()
{
var db = new CustomContext();
((IObjectContextAdapter)db).ObjectContext.ObjectMaterialized += OnObjectMaterialized;
return db;
}
private void OnObjectMaterialized(object sender, ObjectMaterializedEventArgs args)
{
if (args.Entity is User)
{
(args.Entity as User).Repository = this;
}
if (args.Entity is Role)
{
(args.Entity as Role).Repository = this;
}
}
}
public class CustomContext : DbContext
{
public CustomContext()
: base()
{
Configuration.LazyLoadingEnabled = false;
}
public DbSet<User> Users { get; set; }
public DbSet<Role> Roles { get; set; }
}
When running the following code, for each User entity returned, there are duplicate pairs for each Role entity in user.Roles
IRepository repository = new Repository();
ICollection users = repository.GetAllUsers();
foreach (User user in users)
{
foreach (Role role in user.Roles)
{
...
}
}
The problem occurs regardless of whether or not EF Lazy Loading is enabled, and whether or not the User.Roles property is marked as virtual.
But if I do not eager load Roles in Repository.GetAllUsers() as below and let the lazy-loaded Roles property call Repository.GetRolesByUserId(UserId), then no duplicate Role entities are returned.
public ICollection<User> GetAllUsers()
{
using (var db = CreateContext())
{
// No eager loading
return db.Users.ToList();
}
}
If I change the User.Roles property to always hit the Repository, then no duplicate Role entities are returned.
public ICollection<Role> Roles
{
get { return (_roles = Repository.GetRolesByUserId(UserId)); }
set { _roles = value; }
}
It looks like calling db.Users.Include(u => u.Roles) triggers the User.Roles property's get() action which causes the Roles collection to be populated twice.
I've confirmed that the User.Roles property actually gets populated twice when the IQueryable object is enumerated. e.g. when calling .ToList(). This means, in order to work around this behavipur, there's no way to avoid making changes to the Roles property's get() body. Which means putting EF specific logic in your Domain layer and no longer making it data agnostic.
Is there a way to prevent this from happening? Or is there a better way to achieve lazy-loading after the DbContext has been disposed (outside the Repository layer).

Perhaps something like this could work:
public class Repository : IRepository
{
public bool RunningEagerLoading { get; set; } // false by default
public ICollection<User> GetAllUsers()
{
using (var db = CreateContext())
{
try
{
RunningEagerLoading = true;
return db.Users.Include(u => u.Roles).ToList();
// Materializing (by ToList()) is important here,
// deferred loading would not work
}
finally
// to make sure RunningEagerLoading is reset even after exceptions
{
RunningEagerLoading = false;
}
}
}
// ...
}
public class User
{
// ...
public ICollection<Role> Roles
{
get
{
if (Repository.RunningEagerLoading)
return _roles; // Eager loading cares for creating collection
else
return _roles ?? (_roles = Repository.GetRolesByUserId(UserId));
}
set { _roles = value; }
}
private ICollection<Role> _roles;
public IRepository Repository { private get; set; }
}
But it's an ugly trick-programming in my eyes.

Related

EF change detection does not seem to recognize my updates on an entity

I am trying to create an AddOrUpdate method. Unfortunately, it seems that the change detection is not kicking in. I just don't see what I am doing wrong here.
Consider the following model:
public class Order
{
public long Id { get; set; }
public string OrderId { get; set; }
// ...
public OrderDetails OrderDetails { get; set; }
}
public class OrderDetails
{
public long Id { get; set; }
// ...
public Order Order { get; set; }
}
This entities should have a one-to-one relationship to each other. An order can't exist without OrderDetails and the other way round.
So this is what my EntityTypeConfigurations looks like:
public class OrderEntityTypeConfiguration : EntityTypeConfiguration<Order>
{
public OrderEntityTypeConfiguration()
{
this.HasKey(e => e.Id);
this.HasRequired(e => e.OrderDetails)
.WithRequiredPrincipal(e => e.Order);
this.ToTable("Orders");
}
}
public class OrderDetailEntityTypeConfiguration : EntityTypeConfiguration<OrderDetails>
{
public OrderDetailEntityTypeConfiguration()
{
this.HasKey(e => e.Id);
this.ToTable("OrderDetails");
}
}
Now I've got a repository called OrderRepository, with a method called AddOrUpdate().
public class OrderRepository
{
public OrderRepository(OrderDbContext context)
{
// ...
}
public bool Contains(Order order)
{
var result = this.context.OrderSet.SingleOrDefault(e => e.OrderId == order.OrderId);
return result != null;
}
public Order GetOrderByOrderId(string orderId)
{
return this.context.OrderSet
.Include(e => e.OrderDetails)
.SingleOrDefault(e => e.OrderId == orderId);
}
public void AddOrUpdate(Order order)
{
if (this.Contains(order))
{
var result = this.GetOrderByOrderId(order.OrderId);
result = order;
}
else
{
this.context.OrderSet.Add(order);
}
this.context.SaveChanges();
}
}
However in the case where this.Contains(order) evaluates to true the assignment from order to result does not get detected from the ChangeDetection mechanism. The call to SaveChanges() returns 0. Why is that?
The following approach seems to work, but feels kind of hacky.
public void AddOrUpdate(Order order)
{
if (this.Contains(order))
{
var result = this.GetOrderByOrderId(order.OrderId);
order.Id = result.Id;
order.OrderDetails.Id = result.OrderDetails.Id;
this.context.Entry(result).CurrentValues.SetValues(order);
this.context.Entry(result.OrderDetails).CurrentValues.SetValues(order.OrderDetails);
}
else
{
this.context.OrderSet.Add(order);
}
this.context.SaveChanges();
}
Simple assignment result = order will not work, cause EF is tracking(if chage tracking is enabled) object fetched via this.GetOrderByOrderId(order.OrderId) call and stored in result variable and not the order one. So you will need either copy needed fields from order to result somehow or play with Attach(usually would not recommend though).

Add filter to all query entity framework

I want add CompanyID filter to my all entity framework request.Because each user must see just their records.I dont want add filter (x=>x.CompanyID == cID) all methods in business layer.How can i add automaticly filter to requests.
My GetList method in DAL
public List<TEntity> GetList(Expression<Func<TEntity, bool>> filter)
{
using (var context = new TContext())
{
return filter == null
? context.Set<TEntity>().ToList()
: context.Set<TEntity>().Where(filter).ToList();
}
}
Business
public List<FinanceData> GetAll()
{
return _financeDal.GetList(filter:x=>x.CompanyID==_cID);
}
In the Entity Framework Core 2.0, you can use Global Query Filters.
Add filter just to the one entity:
public interface IDelete
{
bool IsDeleted { get; set; }
}
public class Blog : IDelete
{
public int BlogId { get; set; }
public string Name { get; set; }
public string Url { get; set; }
public List<Post> Posts { get; set; }
}
public class Post : IDelete
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public bool IsDeleted { get; set; }
public int BlogId { get; set; }
public Blog Blog { get; set; }
}
// Default method inside the DbContext or your default Context
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(builder);
modelBuilder.Entity<Blog>()
// Add Global filter to the Blog entity
.HasQueryFilter(p => p.IsDeleted == false);
modelBuilder.Entity<Post>()
// Add Global filter to the Post entity
.HasQueryFilter(p => p.IsDeleted == false);
}
If you have many entities, the first way isn't good, Use below code for applying the global filter to all entities(Magic way):
public static class ModelBuilderExtension
{
public static void ApplyGlobalFilters<TInterface>(this ModelBuilder modelBuilder, Expression<Func<TInterface, bool>> expression)
{
var entities = modelBuilder.Model
.GetEntityTypes()
.Where(e => e.ClrType.GetInterface(typeof(TInterface).Name) != null)
.Select(e => e.ClrType);
foreach (var entity in entities)
{
var newParam = Expression.Parameter(entity);
var newbody = ReplacingExpressionVisitor.Replace(expression.Parameters.Single(), newParam, expression.Body);
modelBuilder.Entity(entity).HasQueryFilter(Expression.Lambda(newbody, newParam));
}
}
}
// Default method inside the DbContext or your default Context
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
modelBuilder.Entity<Blog>();
modelBuilder.Entity<Post>();
builder.ApplyGlobalFilters<IDelete>(e => e.IsDeleted == false);
}
And Queries will be:
exec sp_executesql N'SELECT [x].[BlogId], [x].[Name], [x].[Url]
FROM [dbo].[Blog] AS [x]
WHERE [x].[IsDeleted] = 0'
everything you suggest does not work for the following scenario: HasQueryFilter power, but per each HTTP request. ApplyGlobalFilters / OnModelCreating applied once for model creation. But if you reload the page with different request parameters - they won't be taken into account to filter out DbSet.
If you add the filter to GetAll call - another call 'Include'-ing the entity won't have this filter.
We need real global mechanism to filter out DbSets by specific condition - which may change per each request (page refresh).
You can implement IHasCompanyId interface in such entities. And then implement repository pattern as:
public class MyRepository<T>
{
public MyRepository(DbContext dbContext, int companyID)
{
if (dbContext == null)
throw new ArgumentNullException("Null DbContext");
DbContext = dbContext;
DbSet = DbContext.Set<T>();
CompanyID = companyID;
}
protected DbContext DbContext { get; set; }
protected int CompanyID { get; set; }
protected DbSet<T> DbSet { get; set; }
// Add filter here
public virtual IQueryable<T> GetAll()
{
if(typeof(IHasCompanyID).IsAssignableFrom(typeof(T)))
return DbSet.Where(x => x.CompanyID == CompanyID);
else
return DbSet;
}
}
And initialize _financeDal as:
var _financeDal = new MyRepository<TEntity>(dbContext, companyID);
You can also extend the object context and add an extension method that returns IQueryable
Like
public class CustomdbContext : DbContext
{
public IQueryable<TEntity> ApplyCustomerFilter<TEntity>(IQueryable<TEntity> query) where TEntity : Customer
{
return query.Where(x => x.CustomerId == customerctxId);
}
}

Reference to Lookup Entities without Adding New One

I have 2 EF Entities:
public partial class CustomerEntity
{
public int CustomerId { get; set; }
public string CustomerName { get; set; }
public virtual ICollection<RoleEntity> Roles { get; set; }
}
public partial class RoleEntity
{
public int RoleId { get; set; }
public string RoleName { get; set; }
}
This is my insert method:
public int? InsertCustomer(CustomerEntity customer)
{
_context.CustomerEntities.Add(customer);
try
{
return _context.SaveChanges();
}
catch (DbEntityValidationException exception)
{
return null;
}
}
This is method to create new customer:
public int CreateNewCustomer(string Name)
{
// Some mapping to CustomerEntity
var _customerEntity = new CustomerEntity
{
CustomerName = Name,
Roles = new List<RoleEntity>
{
new RoleEntity
{
RoleId = 1
}
}
};
return InsertCustomer(_customerEntity);
}
The RoleEntity is a 'lookup' table, means it has preset records and will never have new one.
Everytime new CustomerEntity is created, it will have one or more role. How can I insert new CustomerEntity without creating new Role in database?
My CreateNewCustomer method above will insert new Customer as well as new Role in database while I only want new Customer whose role reference to existing Role in database (with id 1).
As said, you could load the role from the database and add it to the customer's Roles collection, but you can also use the "new" role as a stub object (without the need to make a database roundtrip):
public int CreateNewCustomer(string Name)
{
var role = new RoleEntity { RoleId = 1 };
AttachEntity(role); // role is "Unchanged" now
// Some mapping to CustomerEntity
var customerEntity = new CustomerEntity
{
CustomerName = Name,
Roles = new List<RoleEntity>{ role } // Will not set role to "Added"
};
return InsertCustomer(customerEntity);
}
I assume CreateNewCustomer is in some kind of repository having a DbContext instance. AttachEntity does nothing but attach the entity to the context:
void AttachEntity<T>(T entity)
{
this._context.Set<T>().Attach(entity);
}
You could load the Role entity from your _content and assign the object to the _customerEntity.
public int? InsertCustomer(CustomerEntity customer, int roleId)
{
var role =_context.Roles.Find(customer);
_customerEntity Roles = new List<RoleEntity>{ role };
return _context.SaveChanges();
}
Just fetch the RoleEntity you want to assign to that customer and add it to the customer ICollection directly.

C# Entity Framework with linq returns null reference

I have a problem with entity framework in C#.
I have 2 entities, User and UserRole. They are bond by relationships User *->1 UserRole
Whenever I use this query in a function:
User user = context.User.Where(i => i.id == id).FirstOrDefault();
return user.UserRole.accessLevel;
The query returns user, but UserRole is null. The User table has roleId which is related to id of UserRole, and the value of roleId when debugging is correct, although UserRole entity is null. This is strange as it never happened before...
I already made sure that my relationships in model and database are correct. I have correct rows added to database.
EDIT:
Sorry, I should've mentioned I use custom testable database controller:
public class DBController : IUnitOfWork
{
readonly ObjectContext context;
const string ConnectionStringName = "MarketPlaceDBEntities";
public DBController()
{
var connectionString =
ConfigurationManager
.ConnectionStrings[ConnectionStringName]
.ConnectionString;
context = new ObjectContext(connectionString);
}
public void Commit()
{
context.SaveChanges();
}
public IObjectSet<Category> Category
{
get { return context.CreateObjectSet<Category>(); }
}
public IObjectSet<ItemComment> ItemComment
{
get { return context.CreateObjectSet<ItemComment>(); }
}
public IObjectSet<ItemRating> ItemRating
{
get { return context.CreateObjectSet<ItemRating>(); }
}
public IObjectSet<Item> Item
{
get { return context.CreateObjectSet<Item>(); }
}
public IObjectSet<ItemSale> ItemSale
{
get { return context.CreateObjectSet<ItemSale>(); }
}
public IObjectSet<ItemScreenshot> ItemScreenshot
{
get { return context.CreateObjectSet<ItemScreenshot>(); }
}
public IObjectSet<UserRole> UserRole
{
get { return context.CreateObjectSet<UserRole>(); }
}
public IObjectSet<User> User
{
get { return context.CreateObjectSet<User>(); }
}
}
And I do operations via it. Maybe it has to do something with my prob.
interface IUnitOfWork
{
IObjectSet<Category> Category { get; }
IObjectSet<ItemComment> ItemComment { get; }
IObjectSet<ItemRating> ItemRating { get; }
IObjectSet<Item> Item { get; }
IObjectSet<ItemSale> ItemSale { get; }
IObjectSet<ItemScreenshot> ItemScreenshot { get; }
IObjectSet<UserRole> UserRole { get; }
IObjectSet<User> User { get; }
void Commit();
}
I had this whole thing working before, but don't know why it went wrong..
EDIT2:
Solved! Thanks RicoSuter.
Enabling lazy loading in constructor of my db controller solved the problem. I thought it was already enabled, because it was set to true in database model, but it looks like that when creating a new context, you have to enable it manually again.
public DBController()
{
var connectionString =
ConfigurationManager
.ConnectionStrings[ConnectionStringName]
.ConnectionString;
context = new ObjectContext(connectionString);
context.ContextOptions.LazyLoadingEnabled = true;
}
try to eagerly load UserRole (join):
context.User.Include("UserRole").Where(i => i.id == id).FirstOrDefault();
or enable lazy loading first:
context.ContextOptions.LazyLoadingEnabled = true;
context.User.Where(i => i.id == id).FirstOrDefault();
otherwise there is no relation to a UserRole in your database...
Try this
User user = context.User.Where(i => i.id == id).FirstOrDefault();
return user==null?null:user.UserRole.accessLevel;
Most simply u can do this:
UserRole user = context.User.Where(i => i.id == id).Select(i => i.UserRole);
return user.accessLevel;
Edit:
Assuming you already have a relation between User and UserRole
User user = context.User.Where(i => i.id == id).FirstOrDefault();
UserRole role = context.UserRole.Where(i => user.Contains(i.id)).FirstOrDefault();
return role.accessLevel;
Assuming you dont have a relation between User and UserRole
int roleid = Convert.ToInt32(context.User.Where(i => i.id == id).Select(i => i.roleid));
UserRole role = context.UserRole.Where(i => i.id == roleid).FirstOrDefault();
return role.accessLevel;
Also if you have relation but cant see UserRole under User than try adding this to your model
public IDisposable User()
{
YourDataContext context = new YourDataContext();
Type ct = context.User.GetType();
return (IDisposable)(ct);
}

How to set NHibernate mappings for 2 entities which share data that is stored in another table?

Given is the following class hierarchy:
Class Diagram http://img535.imageshack.us/img535/4802/personusermanager.jpg
Additional info:
The Person class is not abstract.
A person could be a User, a Manager or something else that implements the IPerson interface.
The Person class must not have any knowledge about its child classes.
A child class could reside in another assembly.
It is also possible that a Person is a User and a Manager as wel. In that case the UserRepository must return a User object for the given PersonId and the ManagerRepository must return a Manager for the same PersonId.
It must also be possible to get the Person (base) part for all objects that implement the IPerson interface via a PersonRepository.
How can this be mapped within NHibernate?
We are using FluentNHibernate 1.2 and NHibernate 3.1.
In our current situation each class has its own table. So we have a Person table, a User table and a Manager table.
I have already tried the following options without success:
Mapping this with inheritence mapping (one table per subclass);
A join with Person in the mapping for User and Manager (without inheritance mapping);
A HasOne mapping with Person in the User and Manager mapping (without the join and inheritance mapping);
As you've no doubt discovered, it is easy enough to map inheritance like this: Person -> User, or Person -> Manager, or Person -> Manager -> User (or alternately, Person -> Manager -> User).
NHibernate does not allow you to promote/demote to or from a subclass. You'd have to run native SQL to promote or demote.
However, if you followed my initial "map" of your inheritance, you should have had an epiphany that using subclasses for what you are trying to do is an inappropriate solution for what you are trying to model. And that's only with two subclasses! What happens when you add more roles?
What you have is a Person, who can be a member of any number of roles, where roles are extensible. Consider this solution (Source on github: https://github.com/HackedByChinese/NHibernateComposition):
(Assume we have an Entity abstract class which handles equality, where to objects of the same type with the same ID are considered equal)
Project: Models
public class Person : Entity, IPerson
{
public virtual string FirstName { get; set; }
public virtual string LastName { get; set; }
public virtual IList<Role> Roles { get; protected set; }
public Person()
{
Roles = new List<Role>();
}
public virtual void AddRole(Role role)
{
if (Roles.Contains(role)) return;
role.Person = this;
Roles.Add(role);
}
public virtual void RemoveRole(Role role)
{
if (!Roles.Contains(role)) return;
role.Person = null;
Roles.Remove(role);
}
}
public interface IPerson
{
string FirstName { get; set; }
string LastName { get; set; }
Int32 Id { get; }
}
public abstract class Role : Entity
{
public virtual Person Person { get; set; }
public virtual string RoleName { get; protected set; }
}
public class User : Role
{
public virtual string LoginName { get; set; }
public virtual string Password { get; set; }
}
Project: Models.B
public class Manager : Role
{
public virtual string Division { get; set; }
public virtual string Status { get; set; }
}
Project: Models.Impl
I placed fluent mappings for both projects into one to save time. There could easily be separate mapping assemblies for Models and Models.B
public class PersonMap : ClassMap<Person>
{
public PersonMap()
{
Id(c => c.Id)
.GeneratedBy.HiLo("100");
Map(c => c.FirstName);
Map(c => c.LastName);
HasMany(c => c.Roles)
.Inverse()
.Cascade.AllDeleteOrphan();
}
}
public class RoleMap : ClassMap<Role>
{
public RoleMap()
{
Id(c => c.Id)
.GeneratedBy.HiLo("100");
DiscriminateSubClassesOnColumn<string>("RoleName");
References(c => c.Person);
}
}
public class UserMap : SubclassMap<User>
{
public UserMap()
{
DiscriminatorValue("User");
Join("User", joined =>
{
joined.Map(c => c.LoginName);
joined.Map(c => c.Password);
});
}
}
Project: Models.Impl.Tests
[TestFixture]
public class MappingTests
{
private ISessionFactory _factory;
#region Setup/Teardown for fixture
[TestFixtureSetUp]
public void SetUpFixture()
{
if (File.Exists("test.db")) File.Delete("test.db");
_factory = Fluently.Configure()
.Database(() => SQLiteConfiguration.Standard
.UsingFile("test.db")
.ShowSql()
.FormatSql())
.Mappings(mappings => mappings.FluentMappings
.AddFromAssemblyOf<PersonMap>())
.ExposeConfiguration(config =>
{
var exporter = new SchemaExport(config);
exporter.Execute(true, true, false);
})
.BuildSessionFactory();
}
[TestFixtureTearDown]
public void TearDownFixture()
{
_factory.Close();
}
#endregion
#region Setup/Teardown for each test
[SetUp]
public void SetUpTest()
{
}
[TearDown]
public void TearDownTest()
{
}
#endregion
[Test]
public void Should_create_and_retrieve_Person()
{
var expected = new Person
{
FirstName = "Mike",
LastName = "G"
};
using (var session = _factory.OpenSession())
using (var tx = session.BeginTransaction())
{
session.SaveOrUpdate(expected);
tx.Commit();
}
expected.Id.Should().BeGreaterThan(0);
using (var session = _factory.OpenSession())
using (var tx = session.BeginTransaction())
{
var actual = session.Get<Person>(expected.Id);
actual.Should().NotBeNull();
actual.ShouldHave().AllProperties().EqualTo(expected);
}
}
[Test]
public void Should_create_and_retrieve_Roles()
{
// Arrange
var expected = new Person
{
FirstName = "Mike",
LastName = "G"
};
var expectedManager = new Manager
{
Division = "One",
Status = "Active"
};
var expectedUser = new User
{
LoginName = "mikeg",
Password = "test123"
};
Person actual;
// Act
expected.AddRole(expectedManager);
expected.AddRole(expectedUser);
using (var session = _factory.OpenSession())
using (var tx = session.BeginTransaction())
{
session.SaveOrUpdate(expected);
tx.Commit();
}
using (var session = _factory.OpenSession())
using (var tx = session.BeginTransaction())
{
actual = session.Get<Person>(expected.Id);
// ignore this; just forcing the Roles collection to be lazy loaded before I kill the session.
actual.Roles.Count();
}
// Assert
actual.Roles.OfType<Manager>().First().Should().Be(expectedManager);
actual.Roles.OfType<Manager>().First().ShouldHave().AllProperties().But(c => c.Person).EqualTo(expectedManager);
actual.Roles.OfType<User>().First().Should().Be(expectedUser);
actual.Roles.OfType<User>().First().ShouldHave().AllProperties().But(c => c.Person).EqualTo(expectedUser);
}
}
If you want to constrain a Person to one instance of a particular role, just put a unique index and mess with the Equals method to check if Id is the same OR RoleName is the same.
You can easily get or check a user's role of any type:
if (person.Roles.OfType<User>().Any())
{
var user = person.Roles.OfType<User>().FirstOrDefault();
}
You can also query roles directly to look up their Person:
var peopleWhoAreManagersInDistrictOne = (from role in session.Query<Manager>()
where role.District == "One"
select role.Person);
You can also see that other assemblies can define additional roles. Manager is in a different assembly than Models.
So, you can see this will do everything you want plus more, despite the fact that it uses a different approach.

Categories