我將嘗試在文本中總結我首先要做的事情。我有一個 DbSets 字典,它具有其他集合的值(在我的情況下是 IEnumerable 或 List)。通過 foreach 回圈,我首先嘗試訪問 DbSet 以查看它是否包含“任何”專案。如果不是這種情況,那么我想繼續使用該值,以便可以將 IEnumerable/List 中定義的值添加到 DbSet 中。最后,我使用 EntityFrameworkCore 保存更改。但是,有些我無法訪問這些 DbSet 或集合,因為在運行時需要解決它們。也許您有更好的方法來做到這一點,因為物體彼此不同,它們在字典中以鍵和值的形式出現...... 所以我真正期待的是可以以動態方式訪問這些 DbSet(鍵)/集合(值),而我不必事先宣告型別。字典只允許一種型別,所以我決定選擇“動態”型別。我不知道還有什么其他選擇可以做到這一點有點干凈......
讓我先總結一下我有哪些 DbSet 型別(它們是我字典中的鍵):
- (KEY 1) ' configContext!.Clients ' 有實際型別:Duende.IdentityServer.EntityFramework.Entities.Client
- (KEY 2) ' configContext!.IdentityResources ' 具有實際型別:Duende.IdentityServer.EntityFramework.Entities.IdentityResource
- (KEY 3) ' configContext!.ApiScopes ' 具有實際型別:Duende.IdentityServer.EntityFramework.Entities.ApiScope
- (關鍵 4)' configContext!.ApiResources ' 具有實際型別:Duende.IdentityServer.EntityFramework.Entities.ApiResource
對于這些值,正在使用其他型別
- (鍵值 1)“ Config.Clients ”具有實際型別:Duende.IdentityServer.Models.Client
- (鍵 2 的值)“ Config.IdentityResources ”具有實際型別:Duende.IdentityServer.Models.IdentityResource
- (鍵 3 的值)“ Config.ApiScopes ”具有實際型別:Duende.IdentityServer.Models.ApiScope
- (鍵 4 的值)“ Config.ApiResources ”具有實際型別:Duende.IdentityServer.Models.ApiResource
筆記
雖然我有不同的型別,但每個鍵都可以從模型映射到物體或從物體映射到模型。因此鍵和值具有 1:1 的關系。鍵和值的區別在于鍵是資料庫物體,值是模型
我的初始代碼:
使用部分:
using Duende.IdentityServer.EntityFramework.DbContexts;
using Duende.IdentityServer.EntityFramework.Mappers;
using Duende.IdentityServer.Models;
using Microsoft.EntityFrameworkCore;
using DbClient = Duende.IdentityServer.EntityFramework.Entities.Client;
using DbIdentityResource = Duende.IdentityServer.EntityFramework.Entities.IdentityResource;
using DbApiScope = Duende.IdentityServer.EntityFramework.Entities.ApiScope;
using DbApiResource = Duende.IdentityServer.EntityFramework.Entitie s.ApiResource;
測驗方法:
private static void Test(this ConfigurationDbContext configContext)
{
Dictionary<dynamic, dynamic> configCollections = new Dictionary<dynamic, dynamic>()
{
{ configContext!.Clients, Config.Clients },
{ configContext!.IdentityResources, Config.IdentityResources },
{ configContext!.ApiScopes, Config.ApiScopes },
{ configContext!.ApiResources, Config.ApiResources },
};
foreach (var configCollection in configCollections)
{
var collection = configCollection!.Key.Any();
if (collection == false)
{
foreach (var configValue in configCollection.Value)
{
configCollection!.Key.Add(configValue.ToEntity());
}
configContext.SaveChanges();
}
}
}
代碼是如何被呼叫的(初始版本)
configContext.Test();
在進行任何新嘗試之前,我收到的初始錯誤:
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException:“Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable<Duende.IdentityServer.EntityFramework.Entities.Client>”不包含“任何”的定義
我試圖修復它,但沒有成功
我的新的第一次嘗試:(首先更改字典,然后呼叫方法)
測驗方法如下所示:
private static void Test<T1, T2, T3, T4, K1, K2, K3, K4>(this ConfigurationDbContext configContext)
我的新詞典:
Dictionary<dynamic, dynamic> configCollections = new Dictionary<dynamic, dynamic>()
{
{ configContext!.Clients.Cast<T1>(), Config.Clients.Cast<K1>() },
{ configContext!.IdentityResources.Cast<T2>(), Config.IdentityResources.Cast<K2>() },
{ configContext!.ApiScopes.Cast<T3>(), Config.ApiScopes.Cast<K3>() },
{ configContext!.ApiResources.Cast<T4>(), Config.ApiResources.Cast<K4>() },
};
方法呼叫:
configContext.Test<DbClient, DbIdentityResource, DbApiScope, DbApiResource, Client, IdentityResource, ApiScope, ApiResource>();
我的第二次新嘗試: 將var 集合更改為 ->
((DbSet<dynamic>)configCollection!.Key).Any();
我的第三次新嘗試: 將var 集合更改為 ->
((DbSet<dynamic>) configCollection!.Key).Cast<dynamic>().Any();
我遇到的新錯誤...
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException:'無法將型別'Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable<Duende.IdentityServer.EntityFramework.Entities.Client>'轉換為'Microsoft.EntityFrameworkCore.DbSet''
有沒有人知道發生了什么?我會很感激的。
更新:通過以下代碼解決了問題:
筆記:
- 使用Duende.IdentityServer.EntityFramework.Mappers每個配置型別都有不同的映射器(只是提一下,因為它們不存在于 Mappers 下,而是存在于 Mappers 的更深層)
- 確保將以下內容添加到您的連接字串“ MultipleActiveResultSets=true; ”
public static void TestExec()
{
List<(IQueryable dbSet, IEnumerable<object> models)> configCollections = new()
{
(configContext!.Clients, Config.Clients),
(configContext!.IdentityResources, Config.IdentityResources),
(configContext!.ApiScopes, Config.ApiScopes),
(configContext!.ApiResources, Config.ApiResources),
};
foreach (var (dbSet, models) in configCollections)
{
if (dbSet.AsQueryable().GetEnumerator().MoveNext() == false)
{
foreach (object configValue in models)
{
dynamic? test = null;
switch (configValue.GetType().Name)
{
case nameof(Client):
test = ClientMappers.ToEntity((dynamic)configValue);
break;
case nameof(IdentityResource):
case nameof(OpenId):
case nameof(Profile):
case nameof(Email):
case nameof(Phone):
case nameof(Address):
test = IdentityResourceMappers.ToEntity((dynamic)configValue);
break;
case nameof(ApiScope):
test = ScopeMappers.ToEntity((dynamic)configValue);
break;
case nameof(ApiResource):
test = ApiResourceMappers.ToEntity((dynamic)configValue);
break;
default:
break;
}
((dynamic)dbSet).Add(test!);
}
configContext.SaveChanges();
}
}
}
uj5u.com熱心網友回復:
我不確定字典是否是這里的最佳選擇。字典相對于串列的優點是您可以通過使用它的鍵非常快速地查找一個值 ( O(1) )。如果您只是列舉鍵或值或鍵/值對,它比串列慢(都是O(n))。
如果您只想存盤值對,請不要使用字典。例如,您可以通過將元組存盤在串列中來做到這一點。在您給出的示例中,您永遠不會通過鍵查找值。這就是你的問題和評論讓我感到困惑的地方。您實際上從未Key用作密鑰,而僅用作存盤。
這顯示了如何將資訊存盤在元組串列中:
List<(IQueryable dbSet, IEnumerable models)> configCollections = new() {
(configContext!.Clients, Config.Clients),
(configContext!.IdentityResources, Config.IdentityResources),
(configContext!.ApiScopes, Config.ApiScopes),
(configContext!.ApiResources, Config.ApiResources),
};
然后,您可以將測驗撰寫為
foreach (var (dbSet, models) in configCollections) {
if (!dbSet.AsQueryable().GetEnumerator().MoveNext()) { // !Any()
foreach (object configValue in models) {
((dynamic)dbSet).Add(((dynamic)configValue).ToEntity());
}
configContext.SaveChanges();
}
}
如果您的配置值類有一個通用的非泛型基類或介面,那么您可以使用 aIEnumerable<CommonBase>而不是IEnumerable. 如果公共基礎包含非泛型ToEntity()方法,那么您可以簡化向 dbset 添加值
((dynamic)dbSet).Add(configValue.ToEntity());
您仍然可以使用字典,但是鍵應該是您要檢索的物體的型別。字典將被宣告為
Dictionary<Type, (IQueryable dbSet, IEnumerable models)> configCollections;
你可以用
if (configCollections.TryGetValue(typeof(Client), out var collections)) {
var (dbSet, models) = collections;
// TODO: Do something with dbSet or models
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/528199.html
標籤:C#字典动态的收藏品
