如何泛化访问DbContext的DbSet成员?我有一个包含以下类型成员的DbContext:publicDbSetJobLevels{get;放;}publicDbSetCountries{get;放;}publicDbSetRaces{get;放;}publicDbSetLanguages{get;放;}publicDbSetTitles{get;放;所有这些都在T:IdNamePairBase的位置,它只有Id和Name成员。我拼命寻找一个公共接口来访问这些成员,将以下MVC3控制器代码概括为一个控制器:publicActionResultEdit(DropDownListModelmodel,Guid){vardbSet=_dbContext.Countries;varnewItems=model.Items.Where(i=>i.IsNew&&!i.IsDeleted).Select(i=>new{i.Name});foreach(variteminnewItems){if(!string.IsNullOrWhiteSpace(item.Name)){varundead=((IEnumerable)dbSet).FirstOrDefault(p=>p.Name.ToLower()==item.Name.ToLower());if(undead!=null){//分配新值以更新到新的char.caseifpresent.undead.Name=item.Name;undead.IsDeleted=false;_dbContext.SaveChanges();继续;}varnewPair=newCountry{Name=item.Name};dbSet.Add(newPair);_db上下文。保存更改();}}returnRedirectToAction("Edit",new{listName=model.ListName});我该如何解决我的问题,现在我需要为每个DbContext成员提供一个控制器,例如上面的DbSetCountriesInDbSetCountries?部分解决方案:类似于下面GertArnold的回答,在我知道_dbContext.Set之前,我在我的上下文类中实现了这个方法来获取特定类型的集合:publicIEnumerableGetDbSetsByType()其中T:class{//varflags=BindingFlags.Public|绑定标志.DeclaredOnly|BindingFlags.Instance;varprops=GetType().GetProperties().Where(p=>p.PropertyType.IsGenericType&&p.PropertyType.Name.StartsWith("DbSet")).Where(p=>p.PropertyType.GetGenericArguments().All(t=>t==typeof(T)));返回props.Select(p=>(DbSet)p.GetValue(this,null));通过使用vardbSet=_dbContext.Set并将大部分方法放在具有通用类型参数的方法中,可以进行一些概括但是,应该在某处进行切换以决定应指定哪种类型以及要创建哪种类型,因为我认为类型作为模型的属性提供(是吗?)。所以它可能看起来不优雅,但它可能更短,使用DRY-er代码。要添加到GertArnold的回答中,我想指出dbContext上有另一个方法重载,它从类型对象返回一个通用DbSet:vardbSet=dbContext.Set(typeof(T))如果你想添加盲对象,那么使用set.Create()方法创建对象,或者如果对象已经使用“new”关键字创建,则可以使用(类似于此答案)varentity=dbSet.Create();进行转换;dbSet.Add(实体);DbEntityEntryentry=context.Entry(实体);entry.CurrentValues.SetValues(你的对象);我一直在寻找这个问题的答案,我发现使用托管可扩展性框架很容易。这篇文章底部有一个更快的方法,但MEF允许使用更具可扩展性的方法。MEF允许您从不同的程序集构建动态访问插件;但它可用于在单个程序集应用程序中快速填充集合。本质上,我们将使用它作为将程序集反映到类中的安全方法。为了使其功能齐全,我还在实体框架模型中实现了策略模式。添加对项目的引用,指向System.ComponentModel.Composition。这将允许访问MEF库。现在,我们需要实现策略模式。如果您没有Interfaces文件夹,请创建一个并添加IEntity.cs,如下所示。IEntity.csnamespaceYour.Project.Interfaces{//////表示与EntityFrameworkCodeFirst一起使用的实体。///publicinterfaceIEntity{//////获取或设置标识符。/////////标识符。///intId{得到;放;}}}现在,每个具体的实体都需要实现这个接口:publicclassMyEntity:IEntity{#regionImplementationofIEntity//////获取或设置标识符。/////////标识符。///publicintId{get;放;}#endregion//OtherPOCOproperties...}我发现这个最佳实践不适用于为每个实体创建单独的接口,除非您在高测试环境中工作。事实上,接口应该只用在需要一定程度抽象的地方;主要是当多个具体类继承时,或者当使用过分热心的控制反转引擎时。如果您的生产模型中的所有内容都有接口,那么您的架构很可能存在重大缺陷。总之,够啰嗦了。现在我们已经“抛光”了所有实体,我们可以使用MEF来组织它们并在您的上下文中填充集合。在您的上下文中,添加一个新属性://////获取上下文中动态填充的DbSet列表。/////////上下文中动态填充的DbSet列表。///[ImportMany(typeof(DbSet))]publicIEnumerable>Sets{get;私有集;这里[ImportMany(typeof(DbSet))]允许MEF填充集合。接下来,为上下文中的每个DbSet添加相应的Export属性:[Export(typeof(DbSet))]publicDbSetMyEntities{get;放;每个Imported和Exported属性都称为“部分”。拼图的最后一块是组成零件。将以下内容添加到上下文的构造函数中://实例化集合列表。集合=新列表>();//创建一个新的类型目录,以保存导出的部件。varcatalog=newTypeCatalog(typeof(DbSet));//创建一个新的CompositionContainer,以匹配所有可导入和导入的部分。varcontainer=newCompositionContainer(目录);//为这个类组合导出和导入的部分。容器。组成部分(这个);现在,幸运的是,您的上下文中应该有一个动态填充的DbSet列表。我使用此方法允许通过扩展方法轻松截断所有表。//////为DbSet对象提供扩展方法。///publicstaticclassDbSetEx{//////截断指定的集合。//////实体的类型。///集合。///截断的集合。publicstaticDbSetTruncate(thisDbSetset)whereTEntity:class,IEntity{set.ToList().ForEach(p=>set.Remove(p));返回集;我在上下文中添加了截断整个数据库的方法。//////截断数据库。///publicvoidTruncateDatabase(){Sets.ToList().ForEach(s=>s.Truncate());保存更改();编辑(大修):上面解决方案现在已贬值。现在必须进行一些调整才能使其正常工作。要使其工作,您需要将DbSet导入类型为“object”的DbSet临时集合,然后将此集合转换为所需接口类型的DbSet。对于基本用途,IEntity接口就足够了。#region动态表列表//////获取上下文中动态填充的DbSet列表。/////////上下文中动态填充的DbSet列表。///publicList>Tables{get;私有集;}//////获取上下文中动态填充的DbSet列表。/////////上下文中动态填充的DbSet列表。///[ImportMany("Sets",typeof(DbSet),AllowRecomposition=true)]privateListTableObjects{get;放;}//////组成集合列表。/////////为使其工作,您需要将DbSet导入到类型为“object”的///DbSet的临时集合中,然后将此集合转换为所需的///接口类型的DbSet。对于基本用途,IEntity接口就足够了。///privatevoidComposeSetsList(){//实例化表列表。表=新列表>();//实例化MEF导入集合。TableObjects=newList();//创建一个新的类型目录,以保留导出的零件。varcatalog=newTypeCatalog(typeof(DbSet));//创建一个新的CompositionContainer,以匹配所有可导入和导入的部分。varcontainer=newCompositionContainer(目录);//为这个类组合导出和导入的部分。container.ComposeParts(这个);//将每个DbSet安全地转换为公共列表作为DbSet。TableObjects.ForEach(p=>Tables.Add(pasDbSet));}#endregion接下来,从构造函数运行CompileSetsList()Facade(显示Web的最佳实现):publicMvcApplicationContext(){//为ExecuteSQL函数启用事务验证。Configuration.EnsureTransactionsForFunctionsAndCommands=true;//禁用延迟加载。Configuration.LazyLoadingEnabled=false;//启用SQL查询的跟踪。Database.Log=msg=>Trace.WriteLine(msg);//使用MEF编译上下文中所有集合的列表。组合集列表();}然后,只需要设置你的DbSets://////获取或设置作业级别。/////////作业级别。///[前任port("Sets",typeof(DbSet))]publicDbSetJobLevels{get;如果所有分享的内容对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处: