les gens! Supposons que nous ayons un ensemble d'interfaces qui présente le problème 'domain: IUser, IAddressBook, IComment
et ainsi de suite. Le supposer que IUser
est défini comme suit:Comment faire en sorte que Linq2Sql comprenne les types personnalisés?
public interface IUser : IAmIdentifiedEntity<int>, IHaveName
{
string FullName { get; set; }
string Email { get; set; }
bool ReceiveNotification { get; set; }
}
public interface IHaveName
{
string Name { get; set; }
}
Dans ma demande, j'utilise des contrats seulement mentionnés, par exemple:
public IUser GetUser(string userName)
{
return Warehouse.GetRepository<IUser>().GetAll()
.First(u => u.Name == userName);
}
Comme vous pouvez le voir, je suis en utilisant une passerelle pour obtenir des données. La méthode GetAll()
du référentiel renvoie IQueryable<TEntity>
, il est donc possible de générer une requête complexe et d'utiliser tous les avantages du chargement paresseux. Quand je l'ai présenté, j'ai pensé à l'appareil de Linq2Sql à l'avenir. Pendant un certain temps, lors du développement du code client, nous utilisions l'implémentation «en mémoire» du stockage de données. Donc tout fonctionne bien. Mais maintenant, il est temps de lier le domaine à SQL Server. J'ai donc commencé à implémenter toute l'infrastructure sur Linq2Sql ... Et quand on a fait une solution simple (inspirée par article de Fredrik Kalseth) et obtenu la première exception, j'ai réalisé toute la tristesse de cette idée ... Voici l'implmentation de IUser
:
public partial class USER : IUser
{
int IHaveID<int>.ID
{
get { return USERID; }
}
string IHaveName.Name
{
get { return USERNAME; }
set { USERNAME = value; }
}
string IUser.FullName
{
get { return USERFULLNAME; }
set { USERFULLNAME = value; }
}
// ... same approach for other properties
}
Et ici - exception:
Exception: System.NotSupportedException:
The member 'Data.IHaveName.Name' has no supported translation to SQL.
Ceci est exception évidente - fournisseur de Linq2Sql ne comprend pas les interfaces externes, mais comment dois-je le résoudre? Je ne peux pas changer les interfaces de domaine pour revenir Linq.Expression comme:
Expression<Func<string>> IHaveName.Name
{
get { return (() => USERNAME); }
set { USERNAME = value(); }
}
parce qu'il rompt tout l'utilisation du code actuel des interfaces de domaine et je ne peux d'ailleurs pas remplacer int
avec Expression<Func<int>>
en raison de croyances religieuses :)
Peut-être, je devrais écrire personnalisée visiteur d'expression pour sauter dans la requête » appel AST de IUser.SomeProperty
et le remplacer par ses sous-AST ...
Pouvez-vous fournir vos pensées là-dessus?
MISE À JOUR. Ici, je devrais écrire quelque chose sur la mise en œuvre Repository
. Regardez GetAll()
source:
public IQueryable<TEntity> GetAll()
{
ITable table = GetTable();
return table.Cast<TEntity>();
}
protected ITable GetTable()
{
return _dataContext.GetTable(_implType);
}
Dans mon exemple, TEntity <=> IUser
et _implType <=> typeof(USER)
MISE À JOUR 2. que j'ai trouvé related question, où OP a un problème aussi bien: besoin d'un certain pont entre les entités ORM en béton et il est entités de domaine. Et j'ai trouvé intéressant the answer: l'auteur a suggéré de créer le visiteur d'expression, qui effectuera la convertion entre les entités (ORM < => Domain).
De nouvelles suggestions? – ajukraine