So haben Sie eine Eins-zu-Viele-Beziehung zwischen Provider
und Article
: Jeder Provider
hat null oder mehr Articles
, und jedes Article
gehört genau zu ein Provider
.
Wenn Sie diese richtig in Entity Framework eine Eins-zu-viele-Beziehung konfiguriert haben, sollte ein Provider einen Verweis auf seine vielen Articles
haben:
public virtual ICollection<Article> Articles{get; set;}
Des Weiteren haben Sie eine Funktion Next
, die als Eingabe ein dauert Objekt der Klasse T
, die eine Klasse, die IModel
implementiert. Next
gibt das nächste Element aus dem DbSet von Ts zurück, vorausgesetzt, Sie haben eine korrekte Definition für das nächste Element.
Anscheinend möchten Sie die Funktion Next so anpassen, dass Sie diese Funktion verwenden können, um die nächste Provider
mit all ihren Articles
zu erhalten.
Allgemeiner: Wenn T ein Typ ist, der in ihm Eins-zu-Viele-Beziehungen richtig entworfen hat, und Sie ein Objekt vom Typ T haben, möchten Sie das T mit der ersten ID höher als die ID des aktuellen T , inklusive all seiner ICollections.
Ich habe diese kleinere Funktionen in Sever unterteilt:
- Eine Funktion, die, da ein Typ T alle Eigenschaften, die ICollection implementieren zurück
- Eine Funktion, die, da ein DbSet alle Elemente der DbSet zurück inklusive all seinen ICollections
diese beide gegeben, und Funktionen wie OrderBy
und FirstOrDefault
werden Sie den ersten Anbieter mit Id größer als die aktuellen Anbieter mit allen Artikeln bekommen können.
static class QueryableExtensions
{
// returns true if PropertyInfo implements ICollection<...>
public static bool ImplementsICollection(this PropertyInfo propertyInfo)
{
return propertyInfo.IsGenericType
&& propertyInfo.GetGenericTypeDefinition() == typeof(ICollection<>);
}
// returns all readable & writable PropertyInfos of type T that implement ICollection<...>
public static IEnumerable<PropertyInfo> CollectionProperties<T>()
{
return typeof(T).GetProperties()
.Where(prop => prop.CanRead
&& prop.CanWrite
&& prop.PropertyType.ImplementICollection();
}
// given an IQueryable<T>, adds the Include of all ICollection<...> T has
public static IQueryable<T> IncludeICollection<T>(IQueryable<T> query)
{
var iCollectionProperties = CollectionProperties<T>();
foreach (var collectionProperty in collectionProperties)
{
query = query.Include(prop.Name);
}
return query;
}
// given a IQueryable<T> and a T return the first T in the query with Id higher than T
// for this we need to be sure every T has an IComparable property Id
// so T should implement interface IId (see below)
public T Next<T>(this IQueryable<T> query, T currentItem)
where T : IId // makes sure every T has aproperty Id
{
T nextElement = query
// keep only those DbSet items that have larger Ids:
.Where(item => currentItem.Id < item.Id)
// sort in ascending Id:
.OrderBy(item => item.Id
// keep only the first element of this sorted collection:
.FirstOrDefault();
return T
}
}
Ich muss sicher sein, dass jedes T eine ID hat, sonst können Sie nicht die nächste ID bekommen. Wahrscheinlich haben Sie diese in Ihrer IModel Schnittstelle:
public Interface IId
{
public int Id {get;}
}
Nach diesen Funktionen werden Ihre Anfrage wie:
public static T Next<T>(T currentElement) where T : class, IModel, IId
{
T data;
if (currentElement.Id >= GetLastId<T>())
return currentElement;
using (DatabaseEntities context = new DatabaseEntities())
{
return context.Set<T>().Next(currentElement);
}
}
Nicht Ihre Frage zu beantworten, aber ich denke, mit 'Id + 1 'zu Ihrem nächsten Element zu erhalten kann gefährlich sein. Wenn eine Zeile in Ihrer Tabelle gelöscht wird, wird eine Ausnahme ausgelöst. – DavidG
Wie wäre es mit einer Antwort, würden Sie bereit sein, eine Liste von Includes für diese Methode zu übergeben? – DavidG
@DavidG Sie haben Recht mit dem ID-Problem, also sollte ich alle Datensätze in einer Liste speichern (vielleicht 3000)? Aber für diese Zeit, dass ich keine Zeile löschen kann, und ja, ich bin offen für die Verwendung enthält. – legomolina