Hello I'm trying to do this:
I have more classes where user can store the files - path to those files is stored in JSON format in DB and files are stored in folders named as the class (so when class name is Foo then files will be stored in Files/Foo/Foobar.pdf).
I have one controller where I'm sending the path to the file which should be deleted. Here I cannot solve the problem, that I need to delete this file path also from database, but I cannot find out how to dynamically get the DbSet.
I searched in many questions here, but almost everytime I have found DbContext.Set(), but this method does not exists in ASP.NET CORE 3.0. Could you help me how to make it?
Here is my Controller:
[HttpGet]
public JsonResult DeleteFile(string id)
{
KeyValuePair<string, string> message;
if (!string.IsNullOrEmpty(id))
{
string filePath = Uri.UnescapeDataString(id);
if (filePath.CheckIfExists())
{
string nameOfInstance = filePath.GetNumberAccordingToFileName();
string tableName = filePath[1..(filePath.IndexOf('/', 1) - 1)];
Type type = Assembly.GetExecutingAssembly()
.GetTypes()
.FirstOrDefault(t => t.Name.Equals(tableName,StringComparison.OrdinalIgnoreCase));
if(type.IsClass)
{
var entity = db.GetDbSet(Activator.CreateInstance(type)); //this is not working
var item = entity.GetDataFromDbase(nameOfInstance,1,0,"Number","ASC","Number",false,out int filteredResultsCount, out int totalResultsCount, false).FirstOrDefault(); //find the item
item = item.DeleteFileFromItem(User.Identity.Name, filePath);
db.Update(item);
var result = db.SaveChanges();
if (result > 0)
{
if (filePath.DeleteFile())
{
message = new KeyValuePair<string, string>(MessagesHandler.Success, $"File {filePath.Substring(filePath.LastIndexOf("/"))} was successfully deleted.");
return Json(new
{
status = true,
message
});
}
else
{
message = new KeyValuePair<string, string>(MessagesHandler.Error, $"File {filePath.Substring(filePath.LastIndexOf("/"))} was not deleted.");
return Json(new
{
status = false,
message
});
}
} //if the changes were not made in DB
message = new KeyValuePair<string, string>(MessagesHandler.Error, $"File {filePath.Substring(filePath.LastIndexOf("/"))} was deleted, error in DB");
return Json(new
{
status = false,
message
});
}
}//error message when file not found
message = new KeyValuePair<string, string>(MessagesHandler.Error, $"File {filePath} not found.");
return Json(new
{
status = false,
message
});
}//error message when filename is empty
message = new KeyValuePair<string, string>(MessagesHandler.Error, $"Field ID cannot be empty");
return Json(new
{
status = false,
message
});
}
and this is the method GetDbSet:
public static Microsoft.EntityFrameworkCore.DbSet<TEntity> GetDbSet<TEntity>(this DataContext db, TEntity t) where TEntity : class
{
Type type = t.GetType();
return (Microsoft.EntityFrameworkCore.DbSet<TEntity>)typeof(DataContext).GetMethod(nameof(DataContext.Set)).MakeGenericMethod(type).Invoke(db, null);
}
Here I got this exception:
System.InvalidCastException HResult=0x80004002 Message=Unable to cast object of type 'Microsoft.EntityFrameworkCore.Internal.InternalDbSet
1[SmartLab_System.Models.TestRequirement]' to type 'Microsoft.EntityFrameworkCore.DbSet
1[System.Object]'.
Method GetDataFromDbase:
public static List<T> GetDataFromDbase<T>(this IEnumerable<T> entity, string searchBy, int take, int skip, string sortBy,
string sortDir, string columnName, bool showDeactivatedItems, out int filteredResultsCount, out int totalResultsCount, bool countResult = true) where T : class
{
IEnumerable<T> helper;
if (!String.IsNullOrEmpty(searchBy))//if any string to search was given
{
//find the properties we would like to search in
var properties = typeof(T).GetProperties()
.Where(x => x.CanRead && columnName.Contains(x.Name, StringComparison.InvariantCultureIgnoreCase) && columnName.Length == x.Name.Length)
.Select(x => x.GetMethod)
.Where(x => !x.IsStatic);
//.ToList();
//list of all items where searched value was found
helper = entity.GetActiveItems(showDeactivatedItems)
.Where(m => properties
.Select(p => p.Invoke(m, null)?.ToString() ?? string.Empty)
.Any(a => a.ToString().Contains(searchBy, StringComparison.InvariantCultureIgnoreCase)) == true);
//.ToList();
}
else//if no string to search was given
{
helper = entity.GetActiveItems(showDeactivatedItems); //all items
}
List<T> result;
if (take < 1)
{
result = helper
.OrderBy(sortBy + " " + sortDir)
.ToList();
}
else
{
result = helper
.OrderBy(sortBy + " " + sortDir)
.Skip(skip)
.Take(take)
.ToList();
}
if (countResult)
{
filteredResultsCount = helper.Count();//how many items is sent
totalResultsCount = entity.Count(); //how many items is in database
}
else
{
filteredResultsCount = 0;//how many items is sent
totalResultsCount = 0;
}
return result;
}
except of calling db.GetDbSet(type)
I have tried also db.GetDbSet(Activator.CreateInstance(type))
but not working.