Dans mon esprit, le champ d'identification d'un objet métier doit être en lecture seule (Ensemble public de get et privé) comme par définition, l'ID ne changera jamais (car il identifie de manière unique un enregistrement dans la base de données).
Ceci crée Un problème lorsque vous créez un nouvel objet (ID non défini non encore), enregistrez-le dans la base de données via une procédure stockée par exemple qui renvoie l'identifiant nouvellement créé, puis comment le stockez-vous dans l'objet si la propriété ID est en lecture seule ? p>
Exemple: P>
Employee employee = new Employee(); employee.FirstName="John"; employee.LastName="Smith"; EmployeeDAL.Save(employee);
5 Réponses :
Que diriez-vous:
Employee employee = new Employee(EmployeeDAL.GetNextID());
ou .. Employé des employés = Employé.Newemployé ();
Oui, je préfère la solution d'Andra.
Avec cette solution, la méthode NewMemploye () créerait un nouvel enregistrement dans la base de données immédiatement. La prestation est que vous aurez l'employé, mais que si l'utilisateur décide de ne pas sauvegarder l'employé à la fin? Vous devriez revenir à la base de données pour supprimer le dossier qui ne semble pas juste.
Ce ne serait pas trop mauvais. Il peut même simplifier l'accès simultané à votre base de données.
Vous pouvez rendre votre méthode dal simplement renvoyer un objet mis à jour: Vous pouvez également générer un nouvel identifiant dans le code, instancier un objet avec cet identifiant puis demander à votre dal de l'enregistrer . p> Si vous souhaitez que votre objet soit mis à jour lors de la sauvegarde, vous devrez rendre cette propriété publique. P> I Personnellement, j'aime créer des objets em> immuables, Ceux que vous ne pouvez installer qu'une fois en transmettant toutes les valeurs dans le constructeur. Avec cette approche, vous créeriez simplement un objet à enregistrer, puis récupérez-le avec l'ID attribué à partir de la base de données et renvoyez-la à l'appelant. P> P>
Et si l'objet a 50 propriétés? Vous créeriez un nouvel objet, copiez la valeur de toutes les propriétés pour que vous puissiez mettre à jour la propriété ID. Cela fonctionnerait mais cela ne me semble pas juste. Récupération de la base de données fonctionnerait mais cela signifie que vous vous connectez à la base de données deux fois: une fois pour enregistrer l'objet et une fois pour la récupérer (lorsque vous l'avez déjà dans votre code client). Encore une fois ça ne semble pas juste.
Si elle dispose de 50 propriétés, utilisez quelque chose comme CODEPLEX.COM/AUTOMAPPER pour mapper ceux de l'objet A à Objet B
@Anthony: c'est vrai. Voici un avantage: en récupérant à nouveau de la base de données, vous obtenez exactement ce qui vous a été enregistré - peut-être qu'une ficelle a été tronquée ou autre chose. Si vous avez effectué une erreur dans le code, vous devez croire que vous aurez maintenant cet ensemble de données pendant que vous ne le faites pas. Mais encore une fois, il s'agit de diverses approches de conception.
Qu'est-ce qui aurait vraiment aidé dans cette situation si nous avions un concept de "amis" dans .net comme wehad en C ++. Ensuite, vous auriez été facilement solvable.
@Anthony: au lieu de se connecter deux fois, votre procédure stockée peut-elle vous le renvoyer directement
@New en ville: "interne" est l'équivalent de l'ami. En faisant l'identité «Public Get» et «Set interne», le DAL (en supposant que le même assemblage) peut le mettre à jour, mais il resterait en lecture seule pour le reste du monde. C'est probablement une bonne solution.
@Anthony: je suis sceptique sur celui-ci. Nous voulons simplement accorder un accès à une classe particulière, et non pour tous résider dans la même assemblée. Mais à la fin de la journée, vous décidez comment vous voudriez que ce soit.
Vous pouvez faire votre séchis pour l'identifiant Autoriser le jeu uniquement s'il n'a pas déjà été défini avant: Alternativement, je pense que certains cadres prennent en charge ce type de fonctionnalité (par exemple, i Pensez que NHibernate vous permettra d'avoir un setter privé sur un champ d'identification). P> p>
J'aime cette idée, mais vous ne réaliserez que vous ne pouvez pas définir l'identifiant s'il a déjà été défini au moment de l'exécution. Il serait bien que, lors de la compilation, la propriété est en lecture seule (sauf pour le DAL)
Une autre solution possible consiste à déclarer l'employé comme suit: -
public class Employee { public int Id { get; internal set; } }
Et s'ils ne sont pas dans la même assemblée, il est possible d'utiliser: [Assemblage: InternalsVissibleto ("Dal_assemblybly")]
Que diriez-vous uniquement d'autoriser le code en dehors de la DAL à faire référence à l'objet via une interface qui ne fournit pas de setter pour le champ ID (et tout autre champ immuable):
public interface IEmployee { Int32 Id {get;} String Name {get;set;} // ... and so on ... } public class Employee: IEmployee { Int32 Id {get;set;} String Name {get;set;} }
Au fur et à mesure que votre classe d'employé est public (comme cela devrait être le document DAL qui devrait être dans une assemblée distincte doit y accéder), rien n'empêche le code consommateur de créer une instance de la classe d'employé (et donc de modifier l'ID).
Un vieux problème pour lequel je ne crois pas, il y a une "bonne" réponse, juste un tout de mauvais compromis.
Anthony, j'ai supprimé ma réponse. Je pense que je devais compliquer. Je suis d'accord avec @martin Brown. Il n'y a pas de réponse simple au problème. J'irais avec la création d'un nouvel objet, même si cela signifie copier toutes les propriétés.
@Bruno. J'étais sur le point de commenter que votre réponse fonctionnerait probablement. Il semble que la meilleure façon de faire est de faire l'identité interne: le public int Id {obtenir; ensemble interne; } De cette façon, seul le DAL sera capable de le mettre à jour et de permettre à DAL de mettre à jour la propriété "interne": [Assemblée: InternalsVissibleto ("Dal_assembly")] Cette façon pour la propriété DAL L'ID interne sera mis à jour.