I'm using Entity Framework 6. I have 2 classes:
public class BookingRecord
{
public int Id {get; set;}
public int CustomerId {get; set;}
[ForeignKey("CustomerId")]
public virtual Customer Customer {get; set;}
......
}
public class Customer
{
public int Id {get; set;}
public int BusinessUnitId {get; set;}
public int UserId {get; set;}
......
}
And I have BusinessUnitId on User as the Business Unit.
My business logic is:
If User is Administrator, the user can open all booking records in the system. If User is Employee, the user can open all booking records with the same BusinessUnitId on User. If User is RegisteredUser, the user can only open booking records with the same UserId with the user. If User is other roles, the user cannot open booking record at all.
So I have created an Expression for Customer Class for the business logic above.
protected Expression GetUserRoleExtraConditionExpression(ParameterExpression param)
{
Expression expression;
IPrincipal user = HttpContext.Current.User;
if (user.IsInRole(Consts.Roles.Administrator))
{
expression = Expression.Constant(true);
}
else if (user.IsInRole(Consts.Roles.Employee))
{
int businessUnitId = UserManager.FindById(user.Identity.GetUserId()).BusinessUnitId;
expression = Expression.Equal(
Expression.Property(param, typeof(Customer).GetProperty("BusinessUnitId")),
Expression.Constant(businessUnitId));
}
else if (user.IsInRole(Consts.Roles.RegisteredUser))
{
string userId = user.Identity.GetUserId();
expression = Expression.Equal(
Expression.Property(param, typeof(Customer).GetProperty("UserId")),
Expression.Constant(userId));
}
else
{
expression = Expression.Constant(false);
}
return expression;
}
In which ParameterExpression param is a param of type Customer.
For BookingRecord class, I need the same logic to be applied on the Customer property. I.e., BookingRecord.Customer.BusinessUnitId
and BookingRecord.Customer.UserId
must apply the above Expression when it is selected from DB.
How can I re-use the method on BookingRecord?
In other word, how can I get an Expression similar like Expression.Property(param, typeof(Customer).GetProperty("BusinessUnitId"))
but accepts param with the type of BookingRecord and applies on the field of the CustomerField of BookingRecord?
Something like
Expression.Property(param,
typeof(BookingRecord)
.GetProperty(Customer)
.GetProperty("BusinessUnitId"))
Thanks pinkfloydx33.
Expression.Property(Expression.Property(param,...),...)
is just what I was looking for.
So I have the method now as
protected Expression GetUserRoleExtraConditionExpression(Expression param)
{
Expression expression;
IPrincipal user = HttpContext.Current.User;
if (user.IsInRole(Consts.Roles.Administrator))
{
expression = Expression.Constant(true);
}
else if (user.IsInRole(Consts.Roles.Employee))
{
int businessUnitId = UserManager.FindById(user.Identity.GetUserId()).BusinessUnitId;
expression = Expression.Equal(
Expression.Property(param, "BusinessUnitId"),
Expression.Constant(businessUnitId));
}
else if (user.IsInRole(Consts.Roles.RegisteredUser))
{
string userId = user.Identity.GetUserId();
expression = Expression.Equal(
Expression.Property(param, "UserId"),
Expression.Constant(userId));
}
else
{
expression = Expression.Constant(false);
}
return expression;
}
And in caller of Customer class I call it as
GetUserRoleExtraConditionExpression(param);
(param
is Customer
type ParameterExpression
)
and in caller of BookingRecord class I call it as
GetUserRoleExtraConditionExpression(Expression.Property(param, "Customer"))
(param
is a BookingRecord
type ParameterExpression
)