【问题标题】:How to pass a reference to entity class in a function如何在函数中传递对实体类的引用
【发布时间】:2021-10-09 19:04:50
【问题描述】:

我有一个静态方法列表,它们基本上都做同样的事情,只是在不同的表/实体类上:

 public static List<FormFieldHistoryViewModel> GetTextLabelHistory(Guid entryId, int? formFieldId)
        {
            List<FormFieldHistoryViewModel> history = new List<FormFieldHistoryViewModel>();
            List<dbo_FormFieldsFileValues_CT> fields = new List<dbo_FormFieldsFileValues_CT>();

            using (var ctx = new Entities())
            {
                fields = ctx.dbo_FormFieldsFileValues_CT.Where(f => f.FormFieldsID == formFieldId && f.EntryID == entryId).ToList();
            }

            foreach (var row in fields)
            {
                var ffhvm = new FormFieldHistoryViewModel();
                ffhvm.DateEdited = row.DateEdited;
                ffhvm.EditedBy = row.EditedBy;
                ffhvm.Value = row.FileName;
                history.Add(ffhvm);
            }

            return history;
        }

我不想为每个表/实体对象使用一个方法,而是只传递对该类的引用作为参数,以便在您看到 edmxobject 的每个地方使用。我怎样才能做到这一点?

public static List<FormFieldHistoryViewModel> GetTextLabelHistory(Guid entryId, int? formFieldId, type edmxobject)
        {
            List<FormFieldHistoryViewModel> history = new List<FormFieldHistoryViewModel>();
            List<edmxobject> fields = new List<edmxobject>();

            using (var ctx = new Entities())
            {
                fields = ctx.edmxobject.Where(f => f.FormFieldsID == formFieldId && f.EntryID == entryId).ToList();
            }

            foreach (var row in fields)
            {
                var ffhvm = new FormFieldHistoryViewModel();
                ffhvm.DateEdited = row.DateEdited;
                ffhvm.EditedBy = row.EditedBy;
                ffhvm.Value = row.FileName;
                history.Add(ffhvm);
            }

            return history;
        }
}

【问题讨论】:

  • 你应该可以使用传入类型参数,即。 GetTextLabelHistory&lt;T&gt;(...) 我相信在上下文中您可以通过Set(T) 设置您正在操作的类型。 DbContext.Set(Type)
  • 查看泛型:GetTextLabelHistory(Guid entryId, int? formFieldId) where T : class。然后你必须得到那个 T 对象的类型

标签: c# asp.net asp.net-mvc entity-framework


【解决方案1】:

要使这样的东西工作得又好又整洁,您需要一个基本界面来用于您的 Edited* 字段。比如:

public interface IEditable
{
   DateTime DateEdited { get; }
   string EditedBy { get; } // Assuming it stores a name.
   string FileName { get; }
}

那么每个支持的类都会继承这个接口。该方法将更改为:

public List<FormFieldHistoryViewModel> GetTextLabelHistory<T>(Guid entryId, int? formFieldId) where T : class, IEditable

那么您从实体中提取公共字段的查询将是:

using (var ctx = new Entities())
{
    fields = ctx.Set<T>()
       .Where(f => f.FormFieldsID == formFieldId && f.EntryID == entryId)
       .Select(f => new FormFieldHistoryViewModel
       { 
           DateEdited = f.DateEdited,
           EditedBy = f.EditedBy, 
           Filename = f.Filename
       }).ToList();
    return fields;
}

这里的问题很可能是过滤,因为这假设 每个 表都将具有 EntryId 和 FormFieldId,我认为可能不是这种情况,因为您的示例是针对表 FormFieldsFileValues .

如果您想对完全不同的实体做类似的事情,IEditable 可以帮助公开公共字段,但您可能会运气不佳,实际上在方法本身中查询适当的记录。如果您有不同的所需输出视图模型,情况也是如此。同样,您的示例返回一个视图模型,该视图模型的 FileName 与 FormFieldFileValues 对齐,但这不适合您想要返回不同视图模型的情况。

泛型方法适用于所有支持的类的实现相同,而不仅仅是相似。泛型方法的输出必须是值、单个通用类型或与适用类型关联的泛型类。我们可以通过将方法设计为接受IQueryable&lt;T&gt; 而不是在方法内部进行查询来处理通过不同来源(键名、条件等)的过滤,但这仍然需要一个适用于所有实现的单一输出类。例如:

public List<HistoryViewModel> GetHistory<T>(IQueryable<T> query) where T : class, IEditable
{
    string sourceType = typeof(T).Name;
    return query.Select(f => new HistoryViewModel
    {
        SourceType = sourceType,
        SourceId = f.Id,
        DateEdited = f.DateEdited,
        EditedBy = f.EditedBy, 
    }).ToList();
}

IEditable 公开 Id 列而不是特定于类的详细信息,由调用者来构建查询以获取历史视图模型。

如果您确实希望不同的特定历史视图模型与不同的不相关源实体配对,那么通用实现可能无法胜任该任务。

【讨论】:

    【解决方案2】:

    您可以通过 T 使用泛型传入类型参数。

    GetTextLabelHistory<T>(Guid entryId, int? formFieldId) where T : {constraint}
    

    为了使用这种类型对你的数据上下文进行操作,你可以使用 DbContext 的 Set 方法

    myDbContext.Set<T>().SomeOperation()
    

    DbContext.Set()

    Generic Constraints

    【讨论】:

      猜你喜欢
      • 2022-10-24
      • 1970-01-01
      • 2016-03-24
      • 2015-09-22
      • 1970-01-01
      • 1970-01-01
      • 2017-04-05
      • 2012-02-03
      • 1970-01-01
      相关资源
      最近更新 更多