I have set lazy loading for child collections.
I want to post my object with child object, but at the time of mapping,it convert null child object into empty child object.For that i used,
e.g.
.ForMember(d => d.Taxes,
opt => opt.Condition(d => d.Taxes != null));
Its not working well.
then use ConstructUsing method for set child object to null when dto child object is null and also get full model by id when dto child object comes only with ID property.
for Construct Child object
e.g.
.ConstructUsing((Func<ResolutionContext, dao.TaxRate>)(rc=>
AutoMapperNHibernateFactory<dto.TaxRate, dao.TaxRate>.Create(rc)))
Construct method:
public class AutoMapperNHibernateFactory<dto, dao>
where dto : Dinerware.WebService.Public.DTO.Model
where dao : Dyno.DAO.Model, new()
{
public static dao Create(ResolutionContext rc)
{
Int64? Id = ((dto)rc.SourceValue).Id;
if (Id.HasValue && Id.Value > 0)
return DinerwareDaoController<dao>.GetModelById(((dto)rc.SourceValue).Id.Value);
return new dao();
}
}
It works well for dto child object null but not work with dto child object comes only with ID. Above method returns full object but not mapp properly. Thats why resulting child object only with ID.
Thanks in advance please suggest me what to do for,
SaveOrUpdate parent with child collection only when child is not null and Pass child with full model even child comes with only ID property.
You need to configure null destination values:
Mapper.AllowNullDestinationValues = true;
It will map nulls as null.
Related
Given the following:
public class Parent
{
public ChildType childType;
}
public class ChildA : Parent { ... }
public class ChildB : Parent { ... }
public enum ChildType {
childA,
childB
}
public class Content {
public long contentId;
public string? name;
public ICollection<Parent>? contentCollection; <--
...
}
I would like to use the Content class as part of an API. Is it possible to load both children into the collection just using the enum as a discriminator to determine which to cast to?
My understanding is the child objects would need to be loaded from EF as their child class first, then cast to the parent class before being added to the collection as they would be missing properties upon casting back to the child class otherwise. Is this correct? And how can the dbContext be configured to handle this when accessing through the Content class?
Apologies for all the questions, I have not done this before and cannot find an example online. I would like to know any thoughts, pointers or general info before proceeding. Please say if anything is unclear or more info is required.
Edit:
I was trying to map the child objects as their types from the DB, upcast to the parent type to be able to add multiple types to the one collection and then downcast when required for use. As far as I was aware, EF did not have the functionality to do this.
For anyone else who comes across this which needs assistance, I solved my issue by just using ADO.NET which is what entity framework is built around. I was getting stuck by trying to get this working using EF but my belief is it is not able to be done with EF.
Formatting is off a little, and I have renamed everything to suit my original question but here is the solution involved:
Writing an SP to retrieve the data similar to if the objects were stored in a TPH pattern.
Calling that SP using SQLConnection/SQLCommand. (I added this into my context class to keep DAL together but unsure if this is best practice)
public async Task<Collection<Parent>> GetModelMapCollectionAsync(long id) {
Collection<Parent> parentCollection;
using (SqlConnection connection = new SqlConnection(this.Database.GetConnectionString()))
{
using (SqlCommand sqlCommand = new SqlCommand("GetModelMapCollectionAsync", connection))
{
sqlCommand.CommandType = System.Data.CommandType.StoredProcedure;
sqlCommand.Parameters.Add(new SqlParameter("#id", id));
await connection.OpenAsync();
await sqlCommand.ExecuteNonQueryAsync();
using (SqlDataReader sqlDataReader = await sqlCommand.ExecuteReaderAsync())
{
MapCollectionResult(sqlDataReader, out parentCollection);
}
}
}
return parentCollection; }
Using a nuget package called Dapper, create row parsers for each type (easiest solution for readability/simplicity IMO)
Use the discriminator column to determine which parser to use on each row returned from the SP. This creates the child object from the row which allows it to be downcast back later.
Add that parsed object to the collection.
private void MapCollectionResult(SqlDataReader sqlDataReader, out Collection parentCollection)
{
parentCollection= new Collection();
var parentParser = sqlDataReader.GetRowParser<Parent>(typeof(Parent));
var paramClassParser = sqlDataReader.GetRowParser<ParamClass>(typeof(ParamClass));
var childAParser = sqlDataReader.GetRowParser<ChildA>(typeof(ChildA));
var childBParser = sqlDataReader.GetRowParser<ChildB>(typeof(ChildB));
ChildType type = ChildType.None;
Parent parent;
while (sqlDataReader.Read())
{
type = (ChildType)sqlDataReader["ChildTypeId"];
switch(type)
{
case ChildType.ChildA:
parent = childAParser(sqlDataReader);
break;
case ChildType.ChildB:
parent = childBParser(sqlDataReader);
break;
default:
parent = parentParser(sqlDataReader);
break;
}
parent.paramClass = paramClassParser(sqlDataReader);
parentCollection.Add(parent);
}}
How can I make LINQ query (I am using Entity Framework) that returns top n elements in a child collection?
Here are example classes
public class A {
public int ID
public ICollection<B> bData
}
public class B {
public int ID
public string Name
}
This is kind of query I was thinking;
db.A.Where(a => a.ID == query_id).Include(a => a.bData.Take(count)).ToList();
Normally this doesn't work, how could I accomplish this?
The Include method is intended for eager loading the related entity data. It's all or nothing and cannot be used for filtering, sorting, grouping etc.
So what are you asking for can be accomplished with projection (select). It would be simpler if you project to anonymous or custom type (a.k.a. DTO object), because EF does not allow projecting to entity type. But it's still doable by using anonymous type projection in LINQ to Entities query and doing second projection in LINQ to Objects to attach the filtered child collection to its parent entity like this:
var result = db.A
.Where(a => a.ID == query_id)
.Select(a => new { a, bData = a.bData.Take(count).ToList() })
.AsEnumerable() // Switch to LINQ to Object context
.Select(x =>
{
x.a.bData = x.bData;
return x.a;
})
.ToList();
Please note that in order the above to work, bData member should not be virtual or db.Configuration.LazyLoadingEnabled should be false (i.e. lazy loading should be off, otherwise the bData collections will be fully reloaded when first accessed).
I was coding a very simple case with 2 classes: Parent and Child. Parent has n children, and children has 1 Parent. I set up a bidirectional relationship between them.
I was trying to add a business rule to my parent, that rule checked for equality between the child's parent and the instance handling the call. It returned false when it should have returned true. So I simplified everything to get to the root of the problem. So I tested the same equality outside the POCO and it returned true:
Parent parent0 = session.Load<Parent>(0);
Child child = session.Load<Child>(0);
bool externalTest = parent0 == child.Parent;
I then coded a method for my Parent to test the exact same thing:
bool internalTest = parent0.IsRelated(child);
... Parent Class code
public virtual bool IsRelated(Child child)
{
return child.Parent == this;
}
...
And it returns false... I just don't get it. It's the exact same code.
More info:
So to get more info, I modified my test:
Parent parent0 = session.Load<Parent>(0);
Child child = session.Load<Child>(0);
bool externalTest = parent0 == child.Parent;
System.Diagnostics.Debug.WriteLine("outside parent: " + externalTest);
System.Diagnostics.Debug.WriteLine("Number of parent instances before call to IsRelated:" + Parent.NumberOfInstances);
parent0.IsRelated(child, parent0);
System.Diagnostics.Debug.WriteLine("Number of parent instances after call to IsRelated:" + Parent.NumberOfInstances);
... Parent Class code
public virtual void IsRelated(Child child, Parent sameAsThis)
{
bool internalTest = child.Parent == this;
System.Diagnostics.Debug.WriteLine("inside parent:" + internalTest);
bool sameTest = sameAsThis == this;
System.Diagnostics.Debug.WriteLine("this should equal sameAsThis:" + sameTest);
}
...
I passed the parent instance directly to itself and verify it was the same instance. Well it's not, I get another instance created when I enter the IsRelatedMethod.
Here are my test results:
outside parent: True
Number of parent instances before call to IsRelated:1
inside parent:False
this should equal sameAsThis:False
Number of parent instances after call to IsRelated:2
What am I doing wrong ?
For detailed mapping files and pocos, see (http://stackoverflow.com/questions/13253459/relationships-fixup-in-entityframework-vs-nhibernate)
This is because of the proxy that Nhibernate uses to lazy load entities. In your case the child's parent is a proxy instance.
To solve you problem simply change .Load to .Get
.load does not actually hit the database and populate the entity. See this blog post by Ayende for more info
I want to track a list of root objects which are not contained by any element. I want the following pseudo code to work:
using (session1 = [...]) {
IList<FavoriteItem>list = session1.Linq<FavoriteItem>().ToList();
}
list.Add(item1);
list.Add(item2);
list.Remove(item3);
list.Remove(item4);
var item5 = list.First(i => i.Name = "Foo");
item5.Name = "Bar";
using (session2 = [...]) {
session2.Save(list);
}
This should automatically insert item1 and item2, delete item3 and item3 and update item5 (i.e. I don't want to call sesssion.SaveOrUpdate() for all items separately.
Is it possible to define a pseudo entity that is not associated with a table? For example I want to define the class Favorites and map 2 collection properties of it and than I want to write code like this:
using (session1 = [...]) {
var favs = session1.Linq<Favorites>();
}
favs.FavoriteColors.Add(new FavoriteColor(...));
favs.FavoriteMovies.Add(new FavoriteMovie(...));
using (session2 = [...]) {
session.SaveOrUpdate(favs);
}
FavoriteColors and FavoriteMovies are the only properties of the Favorites class and are of type IList and IList. I do only want to persist the these two collection properties but not the Favorites class.
Actually I want a IPersistentCollection object that tracks adds and removes that belongs to no parent entity and stands for itself (the same stuff that happens to collection properties of entities, only in my case I have no parent entity). This works perfectly well if the collections belong to an entity in which case I can add and remove items between two sessions.
Any help is much appreciated.
A simpler solution than a pseudo entity would be to wrap the list in an object that manages the things you want.
public class FavoriteList : IEnumerable
{
private List<FavoriteItem> list;
private ISession session;
public FavoriteList(ISession session)
{
list = session.Linq<FavoriteItem>().ToList();
this.session = session;
}
public void Add(FavoriteItem item)
{
session.SaveOrUpdate(item);
list.Add(item);
}
public void Remove(FavoriteItem item)
{
session.Delete(item); //or something like that
list.Remove(item);
}
public IEnumerator GetEnumerator()
{
return (list as IEnumerable).GetEnumerator();
}
}
I still have not found a real solution to this problem. My work around so far is that I have added the collection as a child collection property to another entity from which only one instance exists so far. But this solution breaks if there will be more instances of this entity and it has the disadvantage that the version of it is incremented every time a item is added or removed.
The other work around would have been to create a pseudo entity with no properties/columns (except an ID).
The third alternative I could think of is recreating the whole collection every time which is quite slow and does not work if other entities are referencing one of the items.
The last alternative would be to reimplement the dirty checking functionality myself but this would add some complexity and code duplication.
If somebody knows better alternatives I would be glad for any comments.
I'm working on a project with NHibernate that classes similar to the following:
public class Parent {
public IList Children {get;set;}
// ...
}
public class Child {
// ...
}
I've got the Children property set to cascade all / delete orphan. Since I'm using the aggregate pattern and instances of Child class will only ever be referenced in the context of a Parent, I don't have a ChildRepository to delete the children directly - only a ParentRepository. However, when I retrieve the Parent object and call Parent.Children.Clear(), the children from the database are never deleted. How can I achieve this?
Deleting child entities is this easy - just remove them from the collection and then save the parent entity. The collection should be mapped with all-delete-orphans.
parent.Children.Clear();
session.Save( parent );
// or
parent.Children.RemoveAt(0);
session.Save( parent );
You can do this without Save() calls as well, unless your FlushMode is Never.
session.BeginTransaction();
parent.Children.Clear();
session.Transaction.Commit();
Using #Chris's UnitOfWork abstractionm this could look like:
using (var uow = new UnitOfWork()) {
parent.Children.Clear();
}