Can you please explain a bit more on this code? I am not getting the idea.
Thank you.
public static class EfAutoRepositoryTypes
{
public static AutoRepositoryTypesAttribute Default { get; private set; }
static EfAutoRepositoryTypes()
{
Default = new AutoRepositoryTypesAttribute(
typeof(IRepository<>),
typeof(IRepository<,>),
typeof(EfRepositoryBase<,>),
typeof(EfRepositoryBase<,,>)
);
}
}
var autoRepositoryAttr = dbContextType.GetSingleAttributeOrNull<AutoRepositoryTypesAttribute>() ??
EfAutoRepositoryTypes.Default;
foreach (var entityTypeInfo in DbContextHelper.GetEntityTypeInfos(dbContextType))
{
var primaryKeyType = EntityHelper.GetPrimaryKeyType(entityTypeInfo.EntityType);
if (primaryKeyType == typeof(int))
{
var genericRepositoryType = autoRepositoryAttr.RepositoryInterface.MakeGenericType(entityTypeInfo.EntityType);
if (!iocManager.IsRegistered(genericRepositoryType))
{
var implType = autoRepositoryAttr.RepositoryImplementation.GetGenericArguments().Length == 1
? autoRepositoryAttr.RepositoryImplementation.MakeGenericType(entityTypeInfo.EntityType)
: autoRepositoryAttr.RepositoryImplementation.MakeGenericType(entityTypeInfo.DeclaringType, entityTypeInfo.EntityType);
iocManager.Register(
genericRepositoryType,
implType,
DependencyLifeStyle.Transient
);
}
}
Hi, I am looking at the database and I cannot see the table that it stores the mapping between Roles and Permissions. Can you guide me please.
Thanks
I will be using it in one View, so where do you think best to add it? On the View itself?
Thank you.
Oh Excellent :)
so if I want to include any feature, I make sure that I load all js/css files (if they are not already loaded) and use them?
Regards Bilal
Thanks a lot :)
Where to place it? In the base class of the Views?
I did thanks, <a class="postlink" href="https://github.com/aspnetzero/aspnet-zero/issues/454">https://github.com/aspnetzero/aspnet-zero/issues/454</a>
Thanks a lot
Hi,
I am seeking your assistance.
In the .Core project, I've added the following:
public class HostEntityBase<TPrimaryKey> : FullAuditedEntity<TPrimaryKey>, IMayHaveTenant
{
public virtual int? TenantId { get; set; }
[Required]
[StringLength(HostEntityConsts.MaxLabelLength)]
public virtual string Label { get; protected set; }
public virtual string Notes { get; protected set; }
public virtual void UpdateLabel(string newLabel)
{
//Validate newLabel
Check.NotNull(newLabel, nameof(newLabel));
Label = newLabel;
}
public virtual void UpdateNotes(string newNotes)
{
Notes = newNotes;
}
protected HostEntityBase()
{
}
}
public class HostEntityWithIntKeyBase : HostEntityBase<int>
{
}
[Table("DrcClothingSize")]
public class ClothingSize : HostEntityWithIntKeyBase, IMayHaveTenant
{
/// <summary>
/// EF
/// </summary>
protected ClothingSize()
{
}
public static ClothingSize Create(string label, string notes = null)
{
var clothingSize = new ClothingSize();
clothingSize.UpdateLabel(label);
clothingSize.UpdateNotes(notes);
return clothingSize;
}
}
public interface IReferenceDataManager<THostEntityBase> : IReferenceDataManager<THostEntityBase, int>
{
}
public interface IReferenceDataManager<THostEntityBase, TPrimaryKey>
{
/// <summary>
/// Gets a list of all available <typeparamref name="THostEntity"/> in the host
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
Task<IReadOnlyList<THostEntityBase>> GetAsync(string filter);
/// <summary>
/// Adds a <typeparamref name="THostEntity"/> record
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
Task CreateAsync(THostEntityBase input);
/// <summary>
/// Adds a <typeparamref name="THostEntity"/> record
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
Task UpdateAsync(THostEntityBase input);
/// <summary>
/// Deletes an existing <typeparamref name="THostEntity"/> record
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
Task DeleteAsync(TPrimaryKey input);
}
public class ReferenceDataManager<THostEntityBase> :
ReferenceDataManager<THostEntityBase, int>,
IReferenceDataManager<THostEntityBase>
where THostEntityBase : HostEntityBase<int>
{
public ReferenceDataManager(
ICacheManager cacheManager,
IRepository<THostEntityBase, int> repository,
IUnitOfWorkManager unitOfWorkManager,
string cacheName = null)
: base(
cacheManager,
repository,
unitOfWorkManager,
cacheName)
{
}
}
public class ReferenceDataManager<THostEntityBase, TPrimaryKey> :
IReferenceDataManager<THostEntityBase, TPrimaryKey>,
ISingletonDependency
where THostEntityBase : HostEntityBase<TPrimaryKey>
{
public string CacheName { get; private set; }
protected ICacheManager CacheManager { get; private set; }
protected IUnitOfWorkManager UnitOfWorkManager { get; private set; }
protected IRepository<THostEntityBase, TPrimaryKey> Repository { get; private set; }
public ReferenceDataManager(ICacheManager cacheManager,
IRepository<THostEntityBase, TPrimaryKey> repository,
IUnitOfWorkManager unitOfWorkManager,
string cacheName = null)
{
UnitOfWorkManager = unitOfWorkManager;
Repository = repository;
CacheManager = cacheManager;
CacheName = cacheName ?? GenerateDefaultCacheName();
}
public virtual async Task<IReadOnlyList<THostEntityBase>> GetAsync(string filter = null)
{
return (await GetListAsync(filter));
}
[UnitOfWork]
public virtual async Task CreateAsync(THostEntityBase input)
{
if ( (await GetAsync() as IReadOnlyList<THostEntityBase>)
.Any(t => t.Label.ToLower().Contains(input.Label.ToLower())))
{
throw new AbpException($"There is already an entity with Label = {input.Label}");
}
var existingEntity = (await GetAsync(input.Label));
if (existingEntity != null)
{
}
using (UnitOfWorkManager.Current.SetTenantId(null))
{
await Repository.InsertAsync(input);
await UnitOfWorkManager.Current.SaveChangesAsync();
}
}
[UnitOfWork]
public virtual async Task UpdateAsync(THostEntityBase input)
{
//Check the entity doesnt exist
var existingEntity = ((await GetAsync() as IReadOnlyList<THostEntityBase>)
.FirstOrDefault(t => t.Label.ToLower().Contains(input.Label.ToLower())));
if (existingEntity != null)
{
if (!existingEntity.Id.Equals(input.Id))
{
throw new AbpException($"There is already an entity with Label = {input.Label}");
}
}
existingEntity.UpdateLabel(input.Label.Trim());
existingEntity.UpdateNotes(input.Notes.Trim());
using (UnitOfWorkManager.Current.SetTenantId(null))
{
await Repository.UpdateAsync(existingEntity);
await UnitOfWorkManager.Current.SaveChangesAsync();
}
}
[UnitOfWork]
public virtual async Task DeleteAsync(TPrimaryKey input)
{
//Get all records from cache
var existingEntity = (await GetAsync() as IReadOnlyList<THostEntityBase>).FirstOrDefault(t => t.Id.Equals(input));
if (existingEntity == null)
{
return;
}
using (UnitOfWorkManager.Current.SetTenantId(null))
{
await Repository.DeleteAsync(existingEntity.Id);
await UnitOfWorkManager.Current.SaveChangesAsync();
}
}
[UnitOfWork]
private async Task<List<THostEntityBase>> GetListAsync(string filter)
{
//Get THostEntityBase from host not any specific tenant
using (UnitOfWorkManager.Current.SetTenantId(null))
{
return await Repository
.GetAllListAsync(
WithFitler(filter)
);
}
}
/// <summary>
/// Prepares a dynamic filter to insert into GetAllListAsync
/// </summary>
/// <param name="filter"></param>
/// <returns></returns>
private Expression<Func<THostEntityBase, bool>> WithFitler(string filter)
{
if (filter.IsNullOrEmpty())
{
return (t => true);
}
return (t => t.Label.ToLower().Contains(filter.ToLower()) || t.Notes.ToLower().Contains(filter.ToLower()));
}
protected virtual string GenerateDefaultCacheName()
{
return GetType().FullName;
}
}
This is just a ReferenceDataManager class that can handle Reading/Updating/Deleting/Creating for all objects that inherit from HostEntityBase.
Now in the .Application project, I have the following:
public interface IClothingSizeAppService : IApplicationService
{
/// <summary>
/// Gets a list of all available ClothingSizes in the host
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
Task<GetClothingSizesOutput> GetClothingSizes(GetClothingSizeInput input);
/// <summary>
/// Adds or updates a clothing size record
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
Task CreateOrUpdateClothingSize(CreateOrUpdateClothingSizeInput input);
/// <summary>
/// Deletes an existing ClothingSize record
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
Task DeleteClothingSize(EntityDto input);
}
[AbpAuthorize(AppPermissions.Pages_HOSTREFDATA_CLOTHINGSIZE)]
public class ClothingSizeAppService : OnlineSystemsAppServiceBase, IClothingSizeAppService
{
private readonly IReferenceDataManager<ClothingSize> _clothingSizeManager;
private readonly ICacheManager _cacheManager;
private readonly IRepository<ClothingSize> _repository;
private readonly IUnitOfWorkManager _unitOfWorkManager;
public ClothingSizeAppService(ICacheManager cacheManager,
IRepository<ClothingSize> repository,
IUnitOfWorkManager unitOfWorkManager)
{
_cacheManager = cacheManager;
_repository = repository;
_unitOfWorkManager = unitOfWorkManager;
_clothingSizeManager = new ReferenceDataManager<ClothingSize>(_cacheManager, _repository, _unitOfWorkManager, "ClothingSizes");
}
public async Task<GetClothingSizesOutput> GetClothingSizes(GetClothingSizeInput input)
{
var clothingSizes = await _clothingSizeManager.GetAsync(input.Filter);
return new GetClothingSizesOutput
{
Items = clothingSizes.MapTo<List<ClothingSizeListDto>>()
};
}
public async Task CreateOrUpdateClothingSize(CreateOrUpdateClothingSizeInput input)
{
if (input.ClothingSize.Id.HasValue)
{
await UpdateClothingSizeAsync(input);
}
else
{
await CreateClothingSize(input);
}
}
[AbpAuthorize(AppPermissions.Pages_HOSTREFDATA_CLOTHINGSIZE_DELETE)]
public async Task DeleteClothingSize(EntityDto input)
{
var existingClothingSize = await _repository.GetAsync(input.Id);
if (existingClothingSize == null)
{
return;
}
await _clothingSizeManager.DeleteAsync(input.Id);
}
#region Private methods
[AbpAuthorize(AppPermissions.Pages_HOSTREFDATA_CLOTHINGSIZE_EDIT)]
private async Task CreateClothingSize(CreateOrUpdateClothingSizeInput input)
{
var newClothingSize = ClothingSize.Create(input.ClothingSize.Label, input.ClothingSize.Notes);
//Check that this new clothing size doesn't exist
await CheckClothingSizeIfAlreadyExists(newClothingSize.Label);
await _clothingSizeManager.CreateAsync(newClothingSize);
}
[AbpAuthorize(AppPermissions.Pages_HOSTREFDATA_CLOTHINGSIZE_EDIT)]
private async Task UpdateClothingSizeAsync(CreateOrUpdateClothingSizeInput input)
{
//Check that this new clothing size doesn't exist
await CheckClothingSizeIfAlreadyExists(input.ClothingSize.Label, input.ClothingSize.Id);
var existingClothingSize = await _repository.GetAsync(input.ClothingSize.Id.Value);
existingClothingSize.UpdateLabel(input.ClothingSize.Label);
existingClothingSize.UpdateNotes(input.ClothingSize.Notes);
await _clothingSizeManager.UpdateAsync(existingClothingSize);
}
private async Task CheckClothingSizeIfAlreadyExists(string label, int? expectedId = null)
{
var allClothingSizes = await _clothingSizeManager.GetAsync(label);
var existingClothingSize = allClothingSizes.Count > 0 ? allClothingSizes[0] : null;
if (existingClothingSize == null)
{
return;
}
if (expectedId != null && existingClothingSize.Id == expectedId.Value)
{
return;
}
throw new UserFriendlyException(L("ThisClothingsizeAlreadyExists", label));
}
#endregion
}
The problem is in this line:
public ClothingSizeAppService(ICacheManager cacheManager,
IRepository<ClothingSize> repository,
IUnitOfWorkManager unitOfWorkManager)
{
_cacheManager = cacheManager;
_repository = repository;
_unitOfWorkManager = unitOfWorkManager;
_clothingSizeManager = new ReferenceDataManager<ClothingSize>(_cacheManager, _repository, _unitOfWorkManager, "ClothingSizes");
}
I would like to be able to inject IReferenceDataManager<ClothingSize> to the constructor.
I have also another 7 similar classes to ClothingSize and all have the same behavior and share the same object properties. So I thought of creating such a generic way of handling stuff.
Then on the ApplicationService level, I would create a new AppService per Entity.
I know that the framework is already doing it with IRepository<Entity> and others.
Can you please guide me on how to do the same in my custom code?
Many Thanks, Bilal