Question

Je viens d'une procédure stockée et je crée manuellement la couche d'accès aux données.J'essaie de comprendre où je dois intégrer Linq To SQL ou les frameworks d'entités dans ma planification normale.Je sépare normalement la couche métier de la couche DAL et j'utilise un référentiel entre les deux.

Il semble que les gens utiliseront les classes générées de Linq vers SQL, les étendront en utilisant la classe partielle ou effectueront une séparation complète et mapperont les classes Linq générées pour séparer les entités commerciales.J'ai un faible pour les entités commerciales distinctes.Cependant, cela semble contre-intuitif.

L'un de mes derniers projets utilisait DDD et le framework d'entité.Lorsqu'il était nécessaire de mettre à jour un objet, il déplaçait l'entité commerciale vers la couche de référentiel qui, en accédant à la couche DAL, créait un contexte et réinterrogeait ensuite l'objet.Cela permettrait ensuite de mettre à jour les valeurs et de les relancer.

Je n'ai pas vu l'intérêt car le contexte des données n'était pas enregistré et nécessitait une requête supplémentaire pour récupérer l'objet avant la mise à jour.Normalement, je ferais simplement la mise à jour (si la concurrence n'était pas un problème)

Mes questions se résument donc à :

  1. Est-il logique de séparer les classes générées par Linq to SQL en entités métier ?
  2. Le contexte des données doit-il être sauvegardé ou est-ce peu pratique ?

Merci pour votre temps, j'essaie de m'assurer que je comprends.J'aime normalement me séparer car cela rend la compréhension plus claire, même dans certains projets plus petits.

Était-ce utile?

La solution

Je lance actuellement mes propres classes Dto et Datacontext au lieu d'utiliser des fichiers de code générés automatiquement de Linq vers Sql.Pour donner un aperçu de l'architecture/modélisation de ma solution, j'ai un projet "Contract" et un projet "Dal".(Également un projet "Modèle", mais j'essaierai de rester ici concentré sur Dal uniquement).Lancer manuellement mes propres Dtos et Datacontext rend tout beaucoup plus petit et plus simple, je vais donner quelques exemples de la façon dont je procède ici.

Je ne renvoie jamais un objet Dto en dehors du Dal, en fait je m'assure de les déclarer comme internes.La façon dont je les renvoie est de les convertir en interface (les interfaces sont situées dans mon calque "Contrat").Nous allons créer un simple "PersonRepository" qui implémente des interfaces "IPersonRetriever et IPersonSaver".

Contrats :

public interface IPersonRetriever
{
     IPerson GetPersonById(Guid personId);
}

public interface IPersonSaver
{
     void SavePerson(IPerson person);
}

Dal :

    public class PersonRepository : IPersonSaver, IPersonRetriever
    {
        private string _connectionString;

        public PersonRepository(string connectionString)
        {
            _connectionString = connectionString;
        }

        IPerson IPersonRetriever.GetPersonById(Guid id)
        {
            using (var dc = new PersonDataContext(_connectionString))
            {
                return dc.PersonDtos.FirstOrDefault(p => p.PersonId == id);
            }
        }

        void IPersonSaver.SavePerson(IPerson person)
        {
            using (var dc = new PersonDataContext(_connectionString))
            {
                var personDto = new PersonDto
                {
                    Id = person.Id,
                    FirstName = person.FirstName,
                    Age = person.Age
                };

                dc.PersonDtos.InsertOnSubmit(personDto);
                dc.SubmitChanges();
            }
        }
    }

Contexte de données personnelles :

    internal class PersonDataContext : System.Data.Linq.DataContext
    {
        static MappingSource _mappingSource = new AttributeMappingSource(); // necessary for pre-compiled linq queries in .Net 4.0+

        internal PersonDataContext(string connectionString) : base(connectionString, _mappingSource) { }

        internal Table<PersonDto> PersonDtos { get { return GetTable<PersonDto>(); } }
    }

    [Table(Name = "dbo.Persons")]
    internal class PersonDto : IPerson
    {
        [Column(Name = "PersonIdentityId", IsPrimaryKey = true, IsDbGenerated = false)]
        internal Guid Id { get; set; }

        [Column]
        internal string FirstName { get; set; }

        [Column]
        internal int Age { get; set; }

        #region IPerson implementation

        Guid IPerson.Id { get { return this.Id; } }
        string IPerson.FirstName { get { return this.FirstName; } }
        int IPerson.Age { get { return this.Age; } }

        #endregion
    }

Vous devrez ajouter l'attribut "Colonne" à toutes vos propriétés Dto, mais si vous remarquez, s'il existe une corrélation un à un entre ce que vous souhaitez que le champ soit exposé sur l'interface et le nom de la colonne réelle du tableau, vous n'aurez pas besoin d'ajouter aucun des paramètres nommés.Dans cet exemple, mon PersonId dans la base de données est stocké sous le nom "PersonIdentityId", mais je souhaite uniquement que mon interface fasse dire au champ "Id".

C'est comme ça que je fais ma couche Dal, je pense que cette couche devrait être stupide, vraiment stupide.Bête dans le sens où il n'est là que pour les opérations CRUD (Créer, Récupérer, Mettre à jour et Supprimer).Toute la logique métier irait dans mon projet "Modèle", qui consommerait et utiliserait les interfaces IPersonSaver et IPersonRetriever.

J'espère que cela t'aides!

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top