这是 EF 数据库优先的好做法吗?

Is this a good practice for EF Database First?

我和我的同事最近讨论了 EF 中的良好实践。 所以我展示我的一个。

他说有点糊涂

我的做法是以特定方式修改自动生成的 class。 这是我的起始模型:

namespace PCServer.Data
{
    using System;
    using System.Collections.Generic;

    public partial class Post: IEntity
    {
        public int Id { get; set; }
        public string Title { get; set; }
        public string Message { get; set; }
        public DateTime Date { get; set; }

        public virtual Post ParentPost { get; set; }
        public virtual AspNetUser Author { get; set; }
    }
}

我喜欢这样扩展:

public partial class Post
    {
        //This class "do" something, like adding a post or deleting a post
        public static class Do
        {
            public static void AddPost(ref ApplicationDbContext context, string postMessage)
            {
                //Create a post
                Post p = new Post();
                p.Title = "This is an example!";
                p.message = postMessage;
                p.Date = DateTime.UtcNow;

                //Adding to context
                BaseService.Add(post, out context);
            }

            public static void DeletePost(ref ApplicationDbContext context, int postId)
            {
                PostRepository postRepo = new PostRepository(context);

                postRepo.GetById(postId);

                //Removing from context
                BaseService.Remove(post, out context);
            }
        }

        //This class "Get" something, like all posts
        public static class Get
        {
            public static void GetPosts()
            {
                using(ApplicationDbContext context = new ApplicationDbContext())
                {
                    PostRepository postRepo = new PostRepository(context);
                    return postRepo.GetAllPosts();
                }
            }
        }

        //This class "Set" something, like title of the post or the post itself maybe
        public static class Set
        {
            public static void Title(ref ApplicationDbContext context, int postId, string title)
            {
                PostRepository postRepo = new PostRepository(context);
                Post post = postRepo.GetById(postId);
                post.Title = title;

                BaseService.Update(post, out context);
            }

            public static void ChangePost(ref ApplicationDbContext context, int postId, Post post)
            {
                PostRepository postRepo = new PostRepository(context);
                Post dbPost = postRepo.GetById(postId);
                dbPost = post;

                BaseService.Update(dbPost, out context);
            }
        }
    }

所以,当我必须对实体做某事时,我可以(仅作为示例):

ApplicationDbContext c = new ApplicationDbContext();

Post.Do.AddPost(ref c,"Hi!");
IEnumerable<Post> posts = Post.Get.GetPosts();

Post.Set.Title(ref c,100,"Changing title!");

毕竟:

await BaseService.CommitAsync<Post>(c);

所以。 你怎么看?你会用吗?为什么?

谢谢你,对不起post。

任何设计模式的优点之一就是其他人可以理解。我:你是如何设计你的网络服务的?你:我们正在使用存储库模式。我:好的,我明白了。

虽然这绝不是一个全面的答案,但它对理解在何处查找内容以及当您被要求进行更新时哪些内容需要更改有很大帮助。

你有一个你喜欢用的设计模式,但你应该问问自己是否容易被别人理解。

例如,您有一个名为 "Do" 的 class。作为名称,这并没有说明 class 的用途。您的评论表明它 "does something",但是还有其他人会凭直觉理解其中的内容吗?添加和删​​除显然是 "doing" 东西,但为什么不是获取或设置?这对你来说可能有意义,但其他人可能会有不同的看法。

我假设您在团队中工作。如果你的团队打算采用这种模式,那么每个人都需要同意使用它,为此,每个人都需要直观地理解它是如何工作的,更重要的是,如何扩展它。如果他们不这样做,那么您将开始在您的 Do class 中获取您认为不应该存在的方法,并且您将在其他 classes 中放置其他人无法使用的方法发现是因为他们在这方面的工作原理与您的心智模型不同。如果每个人都以不同的方式做事,事情很快就会变得混乱。

关于使用部分 classes 扩展实体,我自己会避免这种情况。实体有明确定义的责任,通过向它们添加代码,您正在分配额外的责任(c.f。Single Responsibility Principle)。诚然,您的额外代码都被分成单独的静态子 classes,但如果是这样,为什么不简单地使它们成为 classes 并在您的应用程序中将它们移动到其他地方?

就 classes 本身而言,带有静态方法的静态 classes 将使单元测试变得极其困难,并且没有理由认为它们应该是静态的,所以我肯定会改变那个。当然,现在您必须实例化它们才能使用它们,这提出了更多将它们移动到其他地方的理由。

关于更技术性的问题,BaseService 在做什么?您正在创建一个上下文,将其 通过引用 (为什么?)传递给 AddPost(例如),然后将其用作 out 中的参数 BaseService.Add。我不确定这里发生了什么,但它看起来不对。

作为一种模式,我会说它需要改进,但仅仅通过尝试拥有一种模式,你就在朝着正确的方向前进。

你没有提到你同事的想法 'good practice' 但我建议你继续讨论这个直到你同意为止。确定您要实现的目标,以及最适合该目标的模式。也许有一个适合的既定模式,但尽量不要过度设计它。我的经验告诉我,我越是尝试从 Entity Framework 中抽象出来,就越难使用其中一些更强大的功能。