incorrect parameter passed to SetRelatedEntityProperty

Posts   
 
    
Mountain
User
Posts: 21
Joined: 01-Apr-2005
# Posted on: 04-Apr-2005 05:57:35   

In our application, we build Users (people who are registered with us) out of Persons (entity with a name, address, phone, etc.). We have a Users table and a Persons table.

In the app, when we reference User.Name, we are relying upon Person.Name to provide that value.

Our problem is that the related entity Person is null in the UserEntity object.

We have the following code: IEntityFactory2 factory; bool debugChoice = false; if (debugChoice) { factory = new UserFactory(); } else { factory = new UserEntityFactory(); } EntityCollection users = new EntityCollection(factory);

If I step into the line that uses UserEntityFactory, the problem goes away. If we use UserFactor, which we need to use, the related Person is null.

I don't believe the problem is in UserFactory. It is just this: public override IEntity2 Create() { return new User(); } public override IEntity2 Create(IEntityFields2 fields) { return new User(fields); }

What's interesting is that the value of rootEntitiesArePkSide is false when I use UserFactory, but true when I use UserEntityFactory. Any idea why this would be?

The end result is that when we should be calling UserEntity.SetRelatedEntityProperty("Person", a person entity object), we are actually calling PersonEntity.SetRelatedEntityProperty("Person", a person entity object)!!! Of course, that winds up hitting the default case ("do nothing"), so no related object is ever set.

I'm pulling my hair out trying to figure out how this could happen. Any ideas?

Thanks.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 04-Apr-2005 10:56:16   

How is 'User' defined as a class? A derived class from UserEntity? rootEntitiesArePkSide is an element of the prefetch paths, do you setup prefetch paths somewhere to fetch the related person entity? (this is a bit unclear from your posting)

Frans Bouma | Lead developer LLBLGen Pro
Mountain
User
Posts: 21
Joined: 01-Apr-2005
# Posted on: 04-Apr-2005 17:46:54   

Otis wrote:

How is 'User' defined as a class? A derived class from UserEntity?

public sealed class User : BusinessEntity2ABC, IEntity2, IBusinessEntity, IPerson

It is a wrapper around UserEntity and it implements IEntity2 (and IEntityCore, etc.). For each interface method, it simply calls the UserEntity method/property.

Otis wrote:

do you setup prefetch paths somewhere to fetch the related person entity? (this is a bit unclear from your posting)

Yes. We have experimented with this a lot. Of course, the prefetch paths work fine when we use a UserEntityFactory, but not with a UserFactory. Here's some simplified code:

public static User GetUser(...)
{
  IPredicateExpression filterExpression = new PredicateExpression();

  filterExpression.Add(
    PredicateFactory.CompareValue(UserFieldIndex.ID, ComparisonOperator.Equal, ID));
  filterExpression.AddWithAnd(...);
            
  EntityCollection items = GetFilteredUsers(filterExpression);
  ...
}

private static EntityCollection GetFilteredUsers(IPredicateExpression filterExpression)
{
  EntityCollection users = new EntityCollection(new UserFactory());
  IRelationPredicateBucket filter = new RelationPredicateBucket();
  filter.Relations.Add(UserEntity.Relations.PersonEntityUsingPersonID);

  filterExpression.Add(
    PredicateFactory.CompareValue(UserFieldIndex.Deleted, ComparisonOperator.Equal, "false"));
  filter.PredicateExpression.Add(filterExpression);

  IPrefetchPath2 prefetchPerson = new PrefetchPath2((int)EntityType.UserEntity);
  prefetchPerson.Add(UserEntity.PrefetchPathPerson, new PersonFactory());
            
  ISortExpression sorter = new SortExpression(
  SortClauseFactory.Create(UserFieldIndex.ID, SortOperator.Ascending));

  DataAccessAdapter adapter = new DataAccessAdapter();
  try
  {
    adapter.FetchEntityCollection(users, filter, 0, sorter, prefetchPerson);
  }

I'm trying to figure out if the problem is related to the fact that we use the Wrapper pattern rather than inheritance for the User class, or whether we are just missing something (such as adding Relations to the filter). Looking at the code, I see the proper relations already exist in the generated code and I feel like the Wrapper design should not interfere with proper utilization of this code:

public static IPrefetchPathElement2 PrefetchPathPerson
{
    get
    {
        return new PrefetchPathElement2(
            new EntityCollection(new PersonEntityFactory()),
            UserEntity.Relations.PersonEntityUsingPersonID, 
            (int)EntityType.UserEntity, (int)EntityType.PersonEntity, 0, null, null, null, null, "Person", RelationType.ManyToOne);
    }
}
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 05-Apr-2005 10:18:09   

The relation is a ManyToOne relation (as shown in the prefetchpath node creation code), which means that the root entity is the FK side, so it then calls the PK entity (not the root entity, but the person entity) to set the related entity, as synchronization logic is always set up from the PK side.

I can't really figure out how you got the rootEntitiesArePkSide == true in one situation as the relation is a m:1 relation so root entities (user entities) will never be the PK side.

Frans Bouma | Lead developer LLBLGen Pro