Base solution for your next web application

Activities of "rcasaca"

To achieve that, i had to built my own CombineExpressions method.

Expression<Func<T, bool>> CombineExpressions<T>(Expression<Func<T, bool>> expression1, Expression<Func<Booking, bool>> expression2)
{
    var parameter = Expression.Parameter(typeof(T));
    var leftVisitor = new ReplaceExpressionVisitor(expression1.Parameters[0], parameter);
    var left = leftVisitor.Visit(expression1.Body);
    var rightVisitor = new ReplaceExpressionVisitor(expression2.Parameters[0], parameter);
    var right = rightVisitor.Visit(expression2.Body);
    return Expression.Lambda<Func<T, bool>>(Expression.AndAlso(left, right), parameter);
}

Function GetBookingPredicate only runs when building the Context. It doesn't run each time I perform a query to db.

protected Expression<Func<Booking, bool>> GetBookingPredicate()
{
    Expression<Func<Booking, bool>> entityTypesPredicate = PredicateBuilder.New<Booking>(true);

    return entityTypesPredicate;
}

protected override Expression<Func<TEntity, bool>> CreateFilterExpression<TEntity>()
{
    var expression = base.CreateFilterExpression<TEntity>();

    if (typeof(IAmBooking).IsAssignableFrom(typeof(TEntity)))
    {
        Expression<Func<Booking, bool>> havePortFilter = GetBookingPredicate();

        expression = CombineExpressions(expression, havePortFilter);
    }
}

What am I missing? Thanks.

Hi ismcagdas,

That's what I've foudn and implement in another usecase that I have in my solution. The question here is, the sql to built is a little more complex than have a List<int> and apply a .Contains on it. I have a List<int,int> and I need to apply them in a .Any filter. I can't find a solution to build it directly via lambda expressions so I was trying to use a PredicateBuilder and apply it.

No luck yet. Any tip?

Answer

Hi ismcagdas,

Sorry for the late reply. I'm still trying to accomplish this. I'm not being able to Replace ISettingManager built in by my new one. The error ComponentNotFoundException: No component for supporting the service CustomerHub.Configuration.IHubSettingManager was found is thrown.

This is what i have in Web.Mvc.CustomerHubWebMvcModule.PreInitialize

Configuration.ReplaceService<ISettingManager, HubSettingManager>(DependencyLifeStyle.Singleton);

I've already have my own IHubSettingManager

public interface IHubSettingManager
{
	Task<string> GetSettingAsync(string Name, long UserId);
}

implemented by HubSettingManager

public class HubSettingManager : SettingManager, IHubSettingManager
{
	public HubSettingManager(
		ISettingDefinitionManager settingDefinitionManager,
		ICacheManager cacheManager,
		IMultiTenancyConfig multiTenancyConfig,
		ITenantStore tenantStore,
		ISettingEncryptionService settingEncryptionService)
		: base(
			  settingDefinitionManager,
			  cacheManager,
			  multiTenancyConfig,
			  tenantStore,
			  settingEncryptionService)
	{
	}
	
	public async Task<string> GetSettingAsync(string Name, long UserId) 
	{
		return "setting.value";
	}
}

What i'm I missing?

Thanks.

Hi gterdem.

I've already tried to use UnitOfWorks, but with no luck. Some examples below.

public override void Execute(int x)
{
	_logger.LogInformation(string.Format("Starting {0}...", nameof(T)));

	using (var unitOfWork = _unitOfWorkManager.Begin())
		foreach (var t in _tenantManager.Tenants)
			using (var tUnitOfWork = _unitOfWorkManager.Begin())
			{
				using (_unitOfWorkManager.Current.SetTenantId(t.Id))
				{
					var list = _externalWSClient.GetList<ItemDto>();
					foreach (var i in list)
					{
						_localRepoService.ImportItemAsync(i).Result;
						//Commit Here
					}
				}

				tUnitOfWork.Complete();
			}

	_logger.LogInformation(string.Format("Finished {0}...", nameof(T)));
}
[UnitOfWork]
public override void Execute(int x)
{
	_logger.LogInformation(string.Format("Starting {0}...", nameof(T)));

	using (_unitOfWorkManager.Current.SetTenantId(t.Id))
	{
		var list = _externalWSClient.GetList<ItemDto>();
		foreach (var i in list)
		{
			_localRepoService.ImportItemAsync(i).Result;
			//Commit Here
		}
	}

	_logger.LogInformation(string.Format("Finished {0}...", nameof(T)));
}

With both, TenantManager works. It retrieves all the tenants and i can iterate over them. What i'm missing right now, is the capability of saving on each item import. The commit only occurs when the job finishes, right after the Finished log.

Hi all, Sorry to post on a closed topic but i have a similar problem.

System.ObjectDisposedException Cannot access a disposed context instance. A common cause of this error is disposing a context instance that was resolved from dependency injection and then later trying to use the same context instance elsewhere in your application. This may occur if you are calling 'Dispose' on the context instance, or wrapping it in a using statement. If you are using dependency injection, you should let the dependency injection container take care of disposing context instances. Object name: 'CustomerHubDbContext'.

System.ObjectDisposedException: Cannot access a disposed context instance. A common cause of this error is disposing a context instance that was resolved from dependency injection and then later trying to use the same context instance elsewhere in your application. This may occur if you are calling 'Dispose' on the context instance, or wrapping it in a using statement. If you are using dependency injection, you should let the dependency injection container take care of disposing context instances. Object name: 'CustomerHubDbContext'. at Microsoft.EntityFrameworkCore.DbContext.CheckDisposed() at Microsoft.EntityFrameworkCore.DbContext.get_DbContextDependencies() at Microsoft.EntityFrameworkCore.DbContext.get_Model() at Microsoft.EntityFrameworkCore.Internal.InternalDbSet1.get_EntityType() at Microsoft.EntityFrameworkCore.Internal.InternalDbSet1.get_EntityQueryable() at Microsoft.EntityFrameworkCore.Internal.InternalDbSet1.System.Collections.Generic.IEnumerable<TEntity>.GetEnumerator() at CustomerHub.Jobs.SyncBusinessPartners.Execute(Int32 x) in C:_GIT\SyncBusinessPartners.cs:line 42

Below the code of SyncBusinessPartners Job (highlighted the row in error - line42)

public class SyncBusinessPartners : BackgroundJob<int>, ITransientDependency
{
	private readonly TenantManager _tenantManager;
	private readonly IAbpSession _abpSession;
	private readonly UserManager _userManager;
	private readonly ILogger<SyncBusinessPartners> _logger;

	public SyncBusinessPartners(
		TenantManager tenantManager,
		IAbpSession abpSession,
		UserManager userManager,
		ILogger<SyncBusinessPartners> logger
	)
	{
		_tenantManager = tenantManager;
		_abpSession = abpSession;
		_userManager = userManager;
		_logger = logger;
		LocalizationSourceName = CustomerHubConsts.LocalizationSourceName;
	}

	public override void Execute(int x)
	{
		_logger.LogInformation(L("JobExecutionStarted", args: $"{nameof(SyncBusinessPartners)}"));

		**foreach (var t in _tenantManager.Tenants)**
		{
			var admin = _userManager.FindByNameAsync("admin").Result;
		}

		_logger.LogInformation(L("JobExecutionFinished", args: nameof(DocumentDto)));
	}
}
Answer

Hi ismcagdas, I've extended Setting entity following this tutorial https://docs.aspnetzero.com/en/common/latest/Extending-Existing-Entities#extending-non-abstract-entities. It added two fields, the fk I needed and Discriminator.

You've mention to create a new SettingManager inheriting from default one, I was able to do that, also replacing the service ISettingManager in PreInitialize on WebMvcModule, but it doesn't allow me to override those methods. Also, I can't see them in default SettingManager as well. I'm I missing something? I accomplish that by replicate the method GetSettingValueForUserAsync in my AppHubSettingProvider.

Nevertheless i'm still missing two more methods, Save and Get based on related entity. Like GetSettingValueForApplication, ChangeSettingForApplication. Should I extend interface SettingManager or create a new one?

Thanks.

Answer

Hi ismcagdas, Ok, i was able to apply your suggestion but since i also need to relate settings with Company e WorkingSites structure. I can't use existing SettingDefinitions. Should i create a new SettingDefiition? New Entity to store them in database?

Showing 1 to 7 of 7 entries