J'écris un objet qui doit toujours avoir certaines valeurs. Plus notablement, il doit toujours avoir une valeur pour Nom code> Propriété. public User(string name, IQueryable<User> allUsers)
{
var matches = allUsers.Where(q => q.Name == name).ToList();
if(matches.Any())
{
// abort object initialization
}
Name = name;
}
9 Réponses :
Je suppose que vous pouvez vérifier et jeter une exception dans le constructeur ou le poste de nom de l'objet, mais Eeehehhhh qui peut venir avec une foule de problèmes et des préoccupations mixtes. Je dis créer l'objet via une usine qui fait cette chèque et retourne null (ou une exception bien nommée). Ou créer l'objet POCO et effectuez la validation via une classe / méthode distincte. P>
Vous devez probablement vérifier le nom duplicate avant de créer l'utilisateur. P>
Vous pourriez avoir une condition de course.
Vous pouvez toujours obtenir des conditions de course :-)
Eh bien, vous venez de lancer une exception. Mais je n'aime pas ce moyen de manipuler ce problème du tout. Au contraire, vous devez créer l'utilisateur via le service et avoir le contrôle de service si le nom est valide ou non. P>
Personnellement, je gère des chèques de logique avant d'instancier. Par exemple: Le présertvalidation code> aurait toutes les vérifications logiques d'entreprise en fonction de vos besoins. p> p>
Ce que vous recherchez est le carte d'identité modèle, ou une sorte de ceci. Il est probablement faux de laisser cette responsabilité dans l'objet lui-même, cela devrait être fait dans la composante créant les entités. Bien sûr, la carte Shaoul soit un fil de sécurité si nécessaire, pour éviter les conditions de course. P>
Je gérerais cela dans la validation d'avoir l'utilisateur dans la collection. Par exemple, si vous éditez une collection d'utilisateurs, puis de les persister à la base de données, la couche de persistance serait responsable de la validation. J'ai toujours considéré que la mauvaise pratique d'avoir un objet est responsable du maintien de tous les autres objets comme celui-ci. Il introduit une relation d'enfant parent avec l'objet lui-même quand il n'y en a pas. Je suggère de mettre en œuvre un moteur de validation de certaines sortes pour gérer cela. P>
Au lieu d'avoir un constructeur public, j'ai une méthode comme celle-ci et un constructeur privé: alors votre code d'appel pourrait utiliser On vaut la peine d'ajouter que la méthode que vous utilisez ces magasins que les noms d'utilisateur sont pris, devraient être mis à jour pour dire que ce nom est pris dans le CRÉCOUSER méthode. Sinon, si vous attendez un moment avant de stocker cet objet dans une base de données ou quelque chose, vous aurez toujours des problèmes. J'ai mis à jour le code ci-dessus pour rendre cela plus clair. P> p> utilisateur myuser = user.createuser ("Steve" ); code> et gérer le retour nul / exception en conséquence. p>
De cette façon, vous pouvez utiliser un iQuéryable code> pour contenir tous les utilisateurs (ou une référence à un référentiel à tous les utilisateurs) et éviter les conditions de course avec le verrouillage.
@Sweko à la fois cette méthode et l'utilisation d'un constructeur comporte des conditions de course s'il n'y a pas de serrures, et les deux peuvent retirer les conditions de course en ajoutant les verrous appropriés.
Au lieu de faire cette validation à l'intérieur de l'objet lui-même, mettez la création, la validation et la sauvegarde de cette entité dans un service. Ce service peut lancer un vous pouvez même plus la validation dans sa propre classe. P> p> validationException code> lorsque le nom d'utilisateur n'est pas unique et pourrait même commencer une transaction pour s'assurer qu'aucune condition de course ne peut se produire. Un bon modèle que j'utilise est le Commande / gestionnaire modèle. Voici un exemple:
Abandonner l'initialisation d'un objet est effectué en lançant une exception dans le constructeur et est recommandé de rejeter une entrée non valide.
public class User
{
public User(String name) {
if (String.IsNullOrWhiteSpace(name)) {
if (name == null) {
throw new System.ArgumentNullException("Cannot be null.", "name");
}
else {
throw new System.ArgumentException("Cannot be empty.", "name");
}
}
}
}
public class SomeDataSource {
public void AddUser(User user) {
// Do your business validation here, and either throw or possibly return a value
// If business rules pass, then add the user
Users.Add(user);
}
}
Merci beaucoup pour une réponse aussi détaillée! J'ai été persuadé d'aller de la route de modèle d'usine que vous avez décrite.
une manière de force brute, définissez tous les champs à NULL, ajoutez l'objet avec des champs NULL, supprimez l'objet.
Cela peut simplement être un code d'échantillon, mais au cas où le cas échéant: vous pouvez fournir un prédicat à
tout code>, de sorte que vous n'ayez pas à passer paroù code>.@Brianrasmussen Les deux ont exactement le même résultat. C'est donc une préférence personnelle que vous utilisez. Le
appelle code> de l'autre main empêchetout court-circuit code> de ne pas évaluer toute la requête.@Servy: Bien sûr, je ne dis pas qu'il doit utiliser
tout code>, mais c'est une option et si la liste n'est pas nécessaire, c'est plus simple et éventuellement plus rapide aussi.Merci pour la pointe sur. Nany ()