Wiem, że to pytanie zostało już zadane, ale nie mogłem znaleźć odpowiedzi, która mnie usatysfakcjonuje. Co próbuję zrobić, to pobrać konkretny DbSet<T>
w oparciu o jego typ nazwy.Znajdź ogólny DbSet w dynamicznym kontakcie DbContext
mam następujące:
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("MyDllAssemblyName")]
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("MyCallingAssemblyName")]
class MyDbContext : DbContext {
public DbSet<ModelA> A { get; set; }
public DbSet<ModelB> B { get; set; }
public dynamic GetByName_SwitchTest(string name) {
switch (name) {
case "A": return A;
case "B": return B;
}
}
public dynamic GetByName_ReflectionTest(string fullname)
{
Type targetType = Type.GetType(fullname);
var model = GetType()
.GetRuntimeProperties()
.Where(o =>
o.PropertyType.IsGenericType &&
o.PropertyType.GetGenericTypeDefinition() == typeof(DbSet<>) &&
o.PropertyType.GenericTypeArguments.Contains(targetType))
.FirstOrDefault();
if (null != model)
return model.GetValue(this);
return null;
}
}
nie mam kłopot samego typu, czy jest za pomocą prostego przełącznika lub refleksji. Muszę jednak zwrócić typ jako dynamiczny, ponieważ nie wiem, jaki będzie typ DbSet. Potem gdzieś indziej w tym samym zespole, używam go w ten sposób:
// MyDbContext MyDbContextInstance..
var model = MyDbContextInstance.GetByName_SwitchTest("A");
var record1 = model.FirstOrDefault(); // It crashes here with RunTimeBinderException
W tym momencie model
zawiera instancję typu InternalDbSet<ModelA>
. Stamtąd Jakiekolwiek użycie zrobić z obiektem model
dostaję RunTimeBinderException: „Microsoft.Data.Entity.Internal.InternalDbSet” nie zawierają definicji „FirstOrDefault”
Śledczej w internecie, znalazłem blog post wyjaśniając, że (Dixit jego bloga):
powodem wywołanie FirstOrDefault() nie jest typem informacje o modelu nie jest dostępna w czasie wykonywania. Powodem, dla którego nie jest dostępny, jest fakt, że typy anonimowe nie są publiczne. Gdy metoda zwracająca instancję tego anonimowego typu zwraca numer System.Object odwołujący się do instancji typu anonimowego - typ , którego informacje nie są dostępne dla programu głównego.
Potem wskazuje, że rozwiązania:
Rozwiązanie jest całkiem proste. Wszystko co musimy zrobić, to otworzyć AssemplyInfo.cs projektu ClassLibrary1 i dodaj następującą linię do niego:
[assembly:InternalsVisibleTo("assembly-name")]
Próbowałem to rozwiązanie w moim kodu, ale to nie działa. Dla informacji mam rozwiązanie asp.net 5 z dwoma zestawami uruchomionymi na Dnx dotnet46. Aplikacja i plik dll zawierający wszystkie moje modele i DbContext. Wszystkie odnośne wywołania, które robię, znajdują się w bibliotece DLL.
Czy to rozwiązanie ma szansę zadziałać? Czy czegoś brakuje? Jakieś wskazówki byłyby bardzo doceniane?
góry dzięki
[EDIT]
Próbowałem wrócić IQueryable<dynamic>
zamiast dynamic
i mogłem zrobić kwerendę podstawową model.FirstOrDefault();
ale przede wszystkim chciałbym, aby móc filtrować na polu też:
var record = model.FirstOrDefault(item => item.MyProperty == true);
jak o zmianie dynamiczny do IEnumerable? –
Kelmen
Zrobiłem coś podobnego (zmieniono na IQueryable) i mimo że mogłem zrobić kilka zapytań takich jak 'model.FirstOrDefault()' to nie pozwoli mi na zrobienie rzeczy takich jak 'model.FirstOrDefault (item => item.MyProperty = = true) '. co zmniejsza użyteczność rzeczy. –
DarkUrse
Znalazłem ten sam problem. Czy masz szansę na rozwiązanie? – JosephGarrone