【发布时间】:2020-12-19 15:57:34
【问题描述】:
您好,我正在尝试这样做:
我有更多类,用户可以在其中存储文件 - 这些文件的路径以 JSON 格式存储在 DB 中,文件存储在名为类的文件夹中(因此,当类名为 Foo 时,文件将存储在 Files/ Foo/Foobar.pdf)。
我有一个控制器,用于发送应该删除的文件的路径。在这里我无法解决问题,我需要从数据库中删除这个文件路径,但我不知道如何动态获取 DbSet。
我在这里搜索了很多问题,但几乎每次我都找到了DbContext.Set(),但是ASP.NET CORE 3.0中不存在此方法。你能帮我怎么做吗?
这是我的控制器:
[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
});
}
这是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);
}
这里我得到了这个异常:
System.InvalidCastException H结果=0x80004002 Message=无法转换类型为“Microsoft.EntityFrameworkCore.Internal.InternalDbSet
1[SmartLab_System.Models.TestRequirement]' to type 'Microsoft.EntityFrameworkCore.DbSet1[System.Object]”的对象。
方法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;
}
除了打电话db.GetDbSet(type)我也试过db.GetDbSet(Activator.CreateInstance(type))但没有用。
【问题讨论】:
-
什么是GetDataFromDbase()?它的目的是什么?
-
您可能需要使用反射。这应该可以解决问题 =>
typeof(DbContext).GetMethod(nameof(DbContext.Set).MakeGenericMethod(type).Invoke(db, null)然后您需要将其转换为正确的类型。 -
感谢您的回答,我现在已经编辑了关于我使用您的代码得到的结果的问题
-
@joakimriedel 我试过这个,但问题是一样的 - 当输入参数它 IQueryable
(在这种情况下 T 应该是我的类)然后当我尝试制作 typeof(T) 我'会得到“对象”然后 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);不起作用
标签: c# entity-framework-core-3.0