none
Inherited Entities not transmitted correctly

    Question

  • Hi

    Now that WCF RIA Services support inheritance I thought I do my new project with it. I have the following situation:

     

    [KnownType(typeof(Supervisor))]
    public class Department {     /* Fields       */     public int Id { getset; }
        // ...
     /* Foreign Keys
         */ 
    
        [StringLength(20)]
        public string Name { getset; }
     
        [Association("Department_Supervisor""SupervisorId""Id", IsForeignKey=true)]
        [DataMember]
        [Include]
        public Doctor Supervisor{ getset; }
        public int? SupervisorId { getset; }
    }
     
     
    And the Supervisor class
     
     
    [Table("User")]
    public class Supervisor : Staff
    {
        public string Token { getset; }
    }
     
     
    Supervisor inherits from Staff, Staff inherits from User and as you can see I use TPH.
    The User class is a bit different to make it work with the AuthenticationService:
     
    [KnownType(typeof(Staff))]
    [KnownType(typeof(Supervisor))]
    [KnownType(typeof(Contractor))]
    public class User : IUser
    {
        [KeyColumn(Order = 0)]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        [ProfileUsage(IsExcluded=true)]
        public int Id { getset; }
    
     
    
     
        [KeyColumn(Order = 1)]
        [Required]
        [StringLength(20, MinimumLength = 2)]
        [RegularExpression(@"^\w{2,20}$")]
        [ProfileUsage(IsExcluded = true)]
        public string Name { getset; }
        // ...
    }
     
     
    With it all set up like this, when I do
     
     
    public Department GetDepartmentById(int id)
    {
        var department = DbContext.Departments
            .Include("Supervisor")
            .Single(p => p.Id == id);
        return department;
    }
     
     
    In the domain service, I can see the Supervisor in the debugger. 
    However on the client side I get an EntityRef<Supervisor> (which is good) but it's entity value is null.
     
    Is it even possible to reference derived entities like this? In my opinion, 
    if you support inheritance, this should be in it. I am using the newest version from NuGet
    (RiaServices.EntityFramework v. 4.1.60730.0).
    Please help :)
    Sunday, January 29, 2012 8:30 AM

Answers

  • I figured it out. The context created two extra navigation properties: Supervisor_Id (int) and Supervisor_Name (string). Those weren't set correctly when creating the data in the initializer.

     

    Trying to configure everything with the fluent API only made it worse and everything started to really look nasty. In the end I just ended up not implementing IUser and cheat in the authentication (simplified):

     

        [EnableClientAccess]
        public class MyAuthService : AuthenticationBase<AuthUser>
        {
            protected override AuthUser GetAuthenticatedUser(IPrincipal principal)
            {
                try
                {
                    using (var context = new MyDataContext())
                    {
                        var dbUser = context.Users.Where(u => u.Username == principal.Identity.Name).FirstOrDefault();
                        if (dbUser != null)
                        {
                            return new AuthUser()
                            {
                                Name = dbUser.Username,
                                Roles = dbUser.Roles
                            };
                        }
                    }
                }
                catch { }
     
                return null;
            }
     
            protected override bool ValidateUser(string userName, string password)
            {
                using (var context = new DataContextSwitzerland())
                {
                    var user = context.Users.Where(u => u.Username == userName && u.Password == password).FirstOrDefault();
                    return user != null;
                }
            }
        }
     
        public class AuthUser : UserBase
        {
            // NOTE: Profile properties can be added here 
            // To enable profiles, edit the appropriate section of web.config file.
     
            // public string MyProfileProperty { get; set; }
        }

     

    Working like a charm now.

     

    Tuesday, January 31, 2012 12:13 AM