Add default value for one entity for tenants from host in AspNetBoilerPlate - multi-tenant

Scenario :
My multitenant project is based on ASPNetBoilerPlate.
I have a "WORK" entity which is IMayHaveTenant. Every tenant must see default Works which is in HOST And also His Works too every where. How I must do that?
I need some codes like : tenantId == id || tenantId is null
Wrong Answer :
using (CurrentUnitOfWork.DisableFilter(AbpDataFilters.MayHaveTenant)){ }
This returns other tenants Works too.

Create an interface, inherit IMayHaveTenant if you want the other built-in features that are for it:
public interface IMayHaveTenantSharedWithHost : IMayHaveTenant
{
}
Implement that interface:
public class Work : Entity, IMayHaveTenantSharedWithHost
{
public int? TenantId { get; set; }
// ...
}
Override CreateFilterExpression in your AbpDbContext subclass and handle that interface:
protected override Expression<Func<TEntity, bool>> CreateFilterExpression<TEntity>()
where TEntity : class
{
Expression<Func<TEntity, bool>> expression = null;
if (typeof(ISoftDelete).IsAssignableFrom(typeof(TEntity)))
{
Expression<Func<TEntity, bool>> softDeleteFilter = e => !IsSoftDeleteFilterEnabled || !((ISoftDelete) e).IsDeleted;
expression = expression == null ? softDeleteFilter : CombineExpressions(expression, softDeleteFilter);
}
// if (typeof(IMayHaveTenant).IsAssignableFrom(typeof(TEntity)))
if (typeof(IMayHaveTenantSharedWithHost).IsAssignableFrom(typeof(TEntity)))
{
Expression<Func<TEntity, bool>> mayHaveTenantFilter = e => !IsMayHaveTenantFilterEnabled || ((IMayHaveTenant)e).TenantId == CurrentTenantId || ((IMayHaveTenant)e).TenantId == null;
expression = expression == null ? mayHaveTenantFilter : CombineExpressions(expression, mayHaveTenantFilter);
}
else if (typeof(IMayHaveTenant).IsAssignableFrom(typeof(TEntity)))
{
Expression<Func<TEntity, bool>> mayHaveTenantFilter = e => !IsMayHaveTenantFilterEnabled || ((IMayHaveTenant)e).TenantId == CurrentTenantId;
expression = expression == null ? mayHaveTenantFilter : CombineExpressions(expression, mayHaveTenantFilter);
}
if (typeof(IMustHaveTenant).IsAssignableFrom(typeof(TEntity)))
{
Expression<Func<TEntity, bool>> mustHaveTenantFilter = e => !IsMustHaveTenantFilterEnabled || ((IMustHaveTenant)e).TenantId == CurrentTenantId;
expression = expression == null ? mustHaveTenantFilter : CombineExpressions(expression, mustHaveTenantFilter);
}
return expression;
}

Related

Is it a clean way to write this function?

I had to write a function or functions that returns accounts by role, by currency, by company, by application type. I decided to make one function that according to the request model returns filtered accounts. My question: Is it a clean way to implement the function?
public List<ResponseModel> Get(RequestModel requestModel)
{
return (from role in Context.UserRoles
where
role.UserId == requestModel.UserId &&
role.Account.CompanyId == requestModel.CompanyId &&
(requestModel.RoleId == null ? true : role.RoleId == requestModel.RoleId) &&
(requestModel.Currencies.Count() == 0 ? true : requestModel.Currencies.Contains(role.Account.Currency)) &&
(requestModel.ApplicationTypes.Count() == 0 ? true : requestModel.ApplicationTypes.Contains(role.Account.Type)) &&
(requestModel.AccountUse == null ? true : role.Account.AccountUse == requestModel.AccountUse) &&
(requestModel.OperationTypeId == 0 ? true : role.OperationTypeId == requestModel.OperationTypeId) &&
!role.Account.IsDeleted &&
!role.Account.Company.IsDeleted
orderby role.Account.FormattedAccount
group role by role.Account into Accounts
select new ResponseModel
{
Id = Accounts.Key.Id.ToString(),
FormattedNumber = Accounts.Key.FormattedAccount,
Number = Accounts.Key.Number,
Currency = Accounts.Key.Currency,
Application = Accounts.Key.Application
}).ToList();
}
I was thinking write a store procedure that returns the same but there are almost 250 SP on the sql server and this function is used a lot.
I also thought split it in small functions but I don't know hot to do it.
If this helps:
public class RequestModel
{
public int AccountId { get; set; }
public int OperationTypeId { get; set; }
public string RoleId {get; set;}
public int CompanyId { get; set; }
public string UserId { get; set; }
public string AccountUse { get; set; }
public List<string> Currencies { get; set; }
public List<string> ApplicationTypes { get; set; }
}
Your solution is correct, easy to read and understand, and its execution side is probably as fast as it gets.
The only thing that I would adjust is the conditionals of the form
someCondition ? true : someOtherCondition
I would replace them with an equivalent
(someCondition || someOtherCondition)
to remove conditional expressions from the where clause. I would also replace collection.Count() == 0 with !collection.Any(), as follows:
return (from role in Context.UserRoles
where
role.UserId == requestModel.UserId &&
role.Account.CompanyId == requestModel.CompanyId &&
(requestModel.RoleId == null || role.RoleId == requestModel.RoleId) &&
(!requestModel.Currencies.Any() || requestModel.Currencies.Contains(role.Account.Currency)) &&
(!requestModel.ApplicationTypes.Any() || requestModel.ApplicationTypes.Contains(role.Account.Type)) &&
(requestModel.AccountUse == null || role.Account.AccountUse == requestModel.AccountUse) &&
(requestModel.OperationTypeId == 0 || role.OperationTypeId == requestModel.OperationTypeId) &&
!role.Account.IsDeleted &&
!role.Account.Company.IsDeleted
orderby role.Account.FormattedAccount
group role by role.Account into Accounts
select new ResponseModel
{
Id = Accounts.Key.Id.ToString(),
FormattedNumber = Accounts.Key.FormattedAccount,
Number = Accounts.Key.Number,
Currency = Accounts.Key.Currency,
Application = Accounts.Key.Application
}).ToList();
In order to keep the interpretation of various RequestModel properties inside the RequestModel class you could provide a Filter property, as follows:
public class RequestModel {
...
public Expression<Func<UserRole,bool>> Filter {
get {
return role =>
(role.UserId == UserId)
&& (role.Account.CompanyId == CompanyId)
&& (RoleId == null || role.RoleId == RoleId)
&& (!Currencies.Any() || Currencies.Contains(role.Account.Currency))
&& (!ApplicationTypes.Any() || ApplicationTypes.Contains(role.Account.Type))
&& (AccountUse == null || role.Account.AccountUse == AccountUse)
&& (OperationTypeId == 0 || role.OperationTypeId == OperationTypeId);
}
}
}
Use it in your where clause like this:
return (from role in Context.UserRoles.Where(requestModel.Filter)
where !role.Account.IsDeleted && !role.Account.Company.IsDeleted
orderby role.Account.FormattedAccount
group role by role.Account into Accounts
select new ResponseModel {
Id = Accounts.Key.Id.ToString(),
FormattedNumber = Accounts.Key.FormattedAccount,
Number = Accounts.Key.Number,
Currency = Accounts.Key.Currency,
Application = Accounts.Key.Application
}).ToList();
Note how all conditions related to requestModel are "hidden" inside the RequestModel instance. This would make future modifications to RequestModel easier, because you wouldn't need to make "parallel modifications" in other parts of the code.

NSubstitute not matching Linq Expression

I am implementing a repository pattern Query class and testing using NSubstitute.
Repository interface:
public interface IMyRepository
{
IQueryable<T> Query<T>(Expression<Func<T, bool>> filter) where T : class;
}
DateTimeProvider interface:
public interface IMyDateTimeProvider
{
DateTime GetDateNow();
}
Application interface:
public interface IMyApplication
{
List<Thing> GetThingsByQuery(int status);
}
Application implementation:
public class MyApplication : IMyApplication
{
private readonly IMyRepository myRepository;
private readonly IMyDateTimeProvider myDateTimeProvider;
public MyApplication(IMyRepository myRepository, IMyDateTimeProvider myDateTimeProvider)
{
this.myRepository = myRepository;
this.myDateTimeProvider = myDateTimeProvider;
}
public List<Thing> GetThingsByQuery(int status)
{
var createdDate = this.myDateTimeProvider.GetDateNow();
return this.myRepository.Query<Thing>(t => t.CreatedDate == createdDate && t.Status == status).ToList();
}
}
Test:
[TestClass]
public class ApplicationTest
{
private IMyApplication myApplication;
private IMyDateTimeProvider myDateTimeProvider;
private IMyRepository myRepository;
[TestMethod]
public void QueriesRepository()
{
// Arrange
var createdDate = new DateTime(2014, 1, 1);
this.myDateTimeProvider.GetDateNow().Returns(createdDate);
const int Status = 1;
// Act
this.myApplication.GetThingsByQuery(Status);
// Assert
this.myRepository.Received().Query<Thing>(t => t.CreatedDate == createdDate && t.Status == Status);
}
[TestInitialize]
public void TestInitialize()
{
this.myRepository = Substitute.For<IMyRepository>();
this.myDateTimeProvider = Substitute.For<IMyDateTimeProvider>();
this.myApplication = new MyApplication(this.myRepository, this.myDateTimeProvider);
}
}
But the test fails with the following message:
NSubstitute.Exceptions.ReceivedCallsException: Expected to receive a call matching:
Query<Thing>(t => ((t.CreatedDate == value(MySolution.Test.ApplicationTest+<>c__DisplayClass0).createdDate) AndAlso (t.Status == 1)))
Actually received no matching calls.
Received 1 non-matching call (non-matching arguments indicated with '*' characters):
Query<Thing>(*t => ((t.CreatedDate == value(MySolution.Application.MyApplication+<>c__DisplayClass0).createdDate) AndAlso (t.Status == value(MySolution.Application.MyApplication+<>c__DisplayClass0).status))*)
The DateTime and Status are being parsed into value() which are different between the Application and the Test.
Why is this? How can I fix this?
For complicate expressions if often find it easier to assert on captured arguments by using callbacks than with Received(). An (incomplete) example:
Expression<Func<Thing, bool>> receivedFilter receivedFilter = null;
myRepository.When(x => x.Query<Thing>(Arg.Any<...>))
.Do(x => receivedQuery = x.Arg<Expression<Func<Thing, bool>>>());
Then, assert on the captured filter expression. It might actually simpler to just execute the expression's filter func (see e.g. here)
Func<Thing, bool> predicate = receivedFilter.Compile();
var matchingThing = new Thing
{ CreatedDate = createdData, Status = Status };
// assert matching
predicate(matchingThing).Should().BeTrue();
// assert non.matching
predicate(nonMatchingThing).Should().BeFalse();
This approach seems to make the test a little more black-boxed but this is in general not a bad thing.
The default equality comparer for an Expression is being used (referential equality):
eg, the expression (t => t.CreatedDate == createdDate && t.Status == Status``) in:
this.myRepository.Received().Query<Thing>(t => t.CreatedDate == createdDate
&& t.Status == Status );
Is a different instance to the expression in:
return this.myRepository.Query<Thing>(t => t.CreatedDate == createdDate
&& t.Status == status ).ToList();
To fix validate this method call check out argument matchers within NSubstitute.
But as an example:
Func<Expression<Thing, bool>, bool> validator =
// TODO this needs to be written properly, based on the expression,
// not its string representation
e => e.Body.ToString() == "t.CreatedDate == createdDate
&& t.Status == Status";
this.myRepository.Received().Query<Thing>(Arg.Is<Expression<Thing, bool>>(validator));

How do I apply a default IComparable<T> in a Linq OrderBy clause

I have a type which has a default sort order as it implements IComparable<T> and IComparable. I'm not getting the results I expect from LINQ , basically it looks as if the IComparable<T> which the type implements is not being applied.
I thought I would get the result I want with an expression in the form:
var result = MyEnumerable<T>.OrderBy(r => r);
where T itself implements IComparable<T>. It's not happening.
I can see related questions where specific IComparable<T> classes are specified for the sort, but I can't find one which uses the default IComparable<T> implemented by T itself.
My syntax is clearly incorrect. What is the correct syntax please?
Thanks in advance.
OrderBy uses the default comparer Comparer<T>.Default which in turn will default to use the IComparable<T> implementation for T, or the non-generic IComparable if the former does not exist.
This code works:
public class Program
{
static void Main(string[] args)
{
var list = new List<Stuff>
{
new Stuff("one"),
new Stuff("two"),
new Stuff("three"),
new Stuff("four")
};
var sorted = list.OrderBy(x => x);
foreach (var stuff in sorted)
{
Console.Out.WriteLine(stuff.Name);
}
}
}
public class Stuff : IComparable<Stuff>
{
public string Name { get; set; }
public Stuff(string name)
{
Name = name;
}
public int CompareTo(Stuff other)
{
return String.CompareOrdinal(Name, other.Name);
}
}
public static class GenericSorter
{
public static IOrderedEnumerable<T> Sort<T>(IEnumerable<T> toSort, Dictionary<string, SortingOrder> sortOptions)
{
IOrderedEnumerable<T> orderedList = null;
foreach (KeyValuePair<string, SortingOrder> entry in sortOptions)
{
if (orderedList != null)
{
if (entry.Value == SortingOrder.Ascending)
{
orderedList = orderedList.ApplyOrder<T>(entry.Key, "ThenBy");
}
else
{
orderedList = orderedList.ApplyOrder<T>(entry.Key, "ThenByDescending");
}
}
else
{
if (entry.Value == SortingOrder.Ascending)
{
orderedList = toSort.ApplyOrder<T>(entry.Key, "OrderBy");
}
else
{
orderedList = toSort.ApplyOrder<T>(entry.Key, "OrderByDescending");
}
}
}
return orderedList;
}
private static IOrderedEnumerable<T> ApplyOrder<T>(this IEnumerable<T> source, string property, string methodName)
{
ParameterExpression param = Expression.Parameter(typeof(T), "x");
Expression expr = param;
foreach (string prop in property.Split('.'))
{
expr = Expression.PropertyOrField(expr, prop);
}
Type delegateType = typeof(Func<,>).MakeGenericType(typeof(T), expr.Type);
LambdaExpression lambda = Expression.Lambda(delegateType, expr, param);
MethodInfo mi = typeof(Enumerable).GetMethods().Single(
method => method.Name == methodName
&& method.IsGenericMethodDefinition
&& method.GetGenericArguments().Length == 2
&& method.GetParameters().Length == 2)
.MakeGenericMethod(typeof(T), expr.Type);
return (IOrderedEnumerable<T>)mi.Invoke(null, new object[] { source, lambda.Compile() });
}
}

Creating linq expression with a subtype restriction

I have this list of type IEnumerable<MyBaseType> for which I am trying to create an extra where-clause to retrieve a specific item in the list. The specific value does only exist on subtype MyFirstType and MySecondType. Not on MyBaseType.
Is it possible to create an expression kind of...
MyList.Where(b => (b is MyFirstType || (b is MySecondType)) && b.SpecificValue == message.SpecificValue);
Above is not working since b is of type MyBaseType and SpecificValue does not exist there. Also note that I do have another subtype MyThirdType that neither has the SpecificValue.
What does work doing what I want is this...
foreach (dynamic u in MyList)
{
if (u is MyFirstType || u is MySecondType)
{
if (u.SpecificValue == message.SpecificValue)
{
//Extracted code goes here
break;
}
}
}
Anyone have an idea how to create an linq expression for the above scenario?
Maybe there is a better solution but as I see it, this could work well enough... If you don't mind performance.
Well then, start by declaring an interface:
public interface IMySpecialType
{
object SpecificValue {get; set;} //you didn't specify what type this is
//all your other relevant properties which first and second types have in common
}
Then, make MyFirstType and MySecondType derive from this interface:
public class MyFirstType : MyBaseType, IMySpecialType
{
//snipet
}
public class MyFirstType : MySecondType, IMySpecialType
{
//snipet
}
Then, filter and cast:
MyList
.Where(b => (b is MyFirstType) || (b is MySecondType))
.Cast<IMySpecialType>()
.Where(b => b.SpecificValue == message.SpecificValue);
//do something
The direct translation of your code to a Linq where clause is
string messageValue = "foo";
var result = baseList.Where(item =>
{
dynamic c = item;
if(item is MyFirstType || item is MySecondType)
{
if( c.SpecificValue == messageValue)
return true;
}
return false;
});
This will require testing the type of the class though and using dynamic - so you might as well cast item to either MyFirstType or MySecondType directly.
An alternative would be using reflection to check if the property exists, using this approach you are not dependent on the actual types of your items as long as they do have the property you are interested in:
string messageValue = "foo";
var result = baseList.Where( item =>
{
var prop = item.GetType().GetProperty("SpecificValue");
if (prop != null && prop.GetValue(item, null) == messageValue)
return true;
else return false;
});
If modifying the class hierarchy is an option you can have you MyFirstType or MySecondType implement an interface that holds the property, then you can use OfType() in your Linq query:
interface ISpecific
{
string SpecificValue { get; set; }
}
class MyFirstType : MyBase, ISpecific
{
public string SpecificValue { get; set; }
}
...
string messageValue = "foo";
var result = baseList.OfType<ISpecific>()
.Where(item => item.SpecificValue == messageValue);
A far more easy way to do that would be to create an interface to mark all your classes having this property SpecificValue. Then it's a child play :
static void Main(string[] args)
{
List<MyBaseType> MyList = new List<MyBaseType>();
ISpecificValue message = new MyFirstType();
MyList.OfType<ISpecificValue>().Where(b => b.SpecificValue == message.SpecificValue);
}
}
class MyBaseType { }
interface ISpecificValue { string SpecificValue { get; set; } }
class MyFirstType : MyBaseType, ISpecificValue
{
public string SpecificValue;
}
class MySecondType : MyBaseType, ISpecificValue
{
public string SpecificValue;
}

Operator overloading in Linq queries

Operator overloading is working perfect in C# code, since I am trying in the following way.
**
public class HostCode
{
public string Code { get; set; }
public string Name { get; set; }
public static bool operator ==(HostCode hc1, HostCode hc2)
{
return hc1.Code == hc2.Code;
}
public static bool operator !=(HostCode hc1, HostCode hc2)
{
return true;
}
}**
I have a clas called HostCode and it contains 2 overloading methods (one for '==' and another for '!=')
And I created a collection of Host Codes below.
**var hostCodes = new List<HostCode>()
{
new HostCode(){ Code = "1", Name = "sreekanth" },
new HostCode(){ Code = "2", Name = "sajan" },
new HostCode(){ Code = "3", Name = "mathew" },
new HostCode(){ Code = "4", Name = "sachin" }
};**
***var hc = new HostCode() { Code = "1", Name = "sreekanth" };***
***var isEq = hostCodes[1] == hc;***
when I am trying like above, the respective operator method fired in HostCode class (in this case it is '=='). So that I can write my custom logic there.
But if Iam trying with a Linq query as below, it is not firing. But in this case also Iam comparing 2 objects having same type.
**var isEqual = from obj in hostCodes where (HostCode)obj == (HostCode)hc select obj;**
Can anyone please help me to find out a way which I can compare 2 objects by Linq queries?
You can use IEqualityComparer or override equals for this purpose.
public class HostCode
{
....
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
return obj as HostCode == null ? false : (obj as HostCode).Code == Code;
}
}
And IEqualityComparer usage is when you have some equality on object and in some functions like Contain, ... you want use some specific equality:
public class EqualityComparer : IEqualityComparer<HostCode >
{
public bool Equals(HostCode x, HostCode y)
{
return y.ID == x.ID;
}
public int GetHashCode(string obj)
{
return obj.GetHashCode();
}
}
Since your question is "how should I compare them for this to work" I would answer "you should overload and use .Equals() instead of =="
And what's with your overload definition of !=?

Resources