《Entity Framework 6 Recipes》中文翻译——第九章EntityFramework在N层架构程序中的应用(二)

在WCF中更新断开实体

问题

  你想使用Windows通信基础(WCF)服务来显示选择、插入、删除和更新数据存储中的数据,并尽可能简单地保存数据库操作。此外,您要使用EntityFramework6 中的First-Code方法来实现数据访问。

解决方案

你有以下模型:

  我们的模型代表blog的文章Post,以及Post的读者评论Comment。为了让事情更清楚,我们已经剥离了我们通常会用到的大部分属性。我们要把所有的数据库代码写在后面一个WCF服务中,使客户可以读取、更新和删除帖子和评论,以及插入新的。要创建服务,做以下工作:

  1、创建一个类库程序,命名为Recipe2

  2、添加EF6的引用,可以使用NuGet Package Manager实现:右击引用,选择NuGet Package Manager,选择EntityFramework6 ,进行加载和安装

  3、添加三个类到Recipe2程序中:Post、Comment、Recipe2Context。Post和Comment代表的POCO实体类,将直接映射到相应的Post和Comment表。recipe2context是数据库上下文对象,将作为实体框架功能的网关。确保你包括所需的WCF数据合同和数据实体类的成员属性

[DataContract(IsReference = true)]
    public class Post
    {
        public Post()
        {
            Comments = new HashSet<Comment>();
        }

        [DataMember]
        public int PostId { get; set; }
        [DataMember]
        public string Title { get; set; }
        [DataMember]
        public virtual ICollection<Comment> Comments { get; set; }
    }
[DataContract(IsReference = true)]
    public class Comment
    {
        [DataMember]
        public int CommentId { get; set; }
        [DataMember]
        public int PostId { get; set; }
        [DataMember]
        public string CommentText { get; set; }
        [DataMember]
        public virtual Post Post { get; set; }
    }
public class EFRecipesEntities : DbContext
    {
        public EFRecipesEntities() : base("name=EFRecipesEntities")
        {
            this.Configuration.ProxyCreationEnabled = false;
        }
        public DbSet<Post> Posts { get; set; }
        public DbSet<Comment> Comments { get; set; }
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            modelBuilder.Entity<Post>()
                .HasMany(e => e.Comments)
                .WithRequired(e => e.Post)
                .WillCascadeOnDelete(false);
        }
    }

 4、在App.Config中添加链接

<connectionStrings>
    <add name="EFRecipesEntities" connectionString="data source=.;initial catalog=School4;persist security info=True;user id=sa;password=123;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" /> </connectionStrings>

  5、接下来添加WCF服务应用程序,为了简单就直接用默认名称作为项目名称,修改IService.cs。添加Recipe2程序和EntityFramework6的引用

 [ServiceContract]
    public interface IService1
    {
        [OperationContract]
        void Cleanup();

        [OperationContract]
        Post GetPostByTitle(string title);

        [OperationContract]
        Post SubmitPost(Post post);

        [OperationContract]
        Comment SubmitComment(Comment comment);

        [OperationContract]
        void DeleteComment(Comment comment);
    }

 6、用以下代码替换Service1.svc.cs 文件中的内容

public class Service1 : IService1
    {
        public void Cleanup()
        {
            using (var context = new EFRecipesEntities())
            {
                context.Database.ExecuteSqlCommand("delete from chapter9.comment");
                context.Database.ExecuteSqlCommand("delete from chapter9.post");
            }

        }
        public void DeleteComment(Comment comment)
        {
            using (var context = new EFRecipesEntities())
            {
                context.Entry(comment).State = EntityState.Deleted;
                context.SaveChanges();
            }

        }
        public Post GetPostByTitle(string title)
        {
            using (var context = new EFRecipesEntities())
        {
                context.Configuration.ProxyCreationEnabled = false;
                var post = context.Posts.Include(p => p.Comments)//System.Data.Entity.dll
                                  .Single(p => p.Title == title);
                return post;
            }

        }

        public Comment SubmitComment(Comment comment)
        {
            using (var context = new EFRecipesEntities())
            {
                context.Comments.Attach(comment);
                if (comment.CommentId == 0)
                {
                    // this is an insert
                    context.Entry(comment).State = EntityState.Added);
                }
                else
                {
                    // set single property to modified, which sets state of entity to modified, but
                    // only updates the single property – not the entire entity
                    context.Entry(comment).Property(x => x.CommentText).IsModified = true;
                }
                context.SaveChanges();
                return comment;
            }
        }
        public Post SubmitPost(Post post)
        {
            using (var context = new EFRecipesEntities())
            {
                context.Entry(post).State =
            // if Id equal to 0, must be insert; otherwise, it's an update
            post.PostId == 0 ? EntityState.Added : EntityState.Modified;
                context.SaveChanges();
                return post;
            }
                
        }
    }

  7、添加Windows Console Application程序作为我们的客户端来测试WCF服务,添加服务引用,同时更新Program.cs文件

 class Program
    {
        static void Main(string[] args)
        {
            using (var client = new ServiceReference1.Service1Client())
            {
                // cleanup previous data
                client.Cleanup();

                // insert a post
                var post = new Post { Title = "POCO Proxies" };
                post = client.SubmitPost(post);

                // update the post
                post.Title = "Change Tracking Proxies";
                client.SubmitPost(post);

                // add a comment
                var comment1 = new Comment
                {
                    CommentText = "Virtual Properties are cool!",
                    PostId = post.PostId
                };
                var comment2 = new Comment
                {
                    CommentText = "I use ICollection<T> all the time",
                    PostId = post.PostId
                };
                comment1 = client.SubmitComment(comment1);
                comment2 = client.SubmitComment(comment2);
                // update a comment
                comment1.CommentText = "How do I use ICollection<T>?";
                client.SubmitComment(comment1);

                // delete comment 1
                client.DeleteComment(comment1);

                // get posts with comments
                var p = client.GetPostByTitle("Change Tracking Proxies");
                Console.WriteLine("Comments for post: {0}", p.Title);
                foreach (var comment in p.Comments)
                {
                    Console.WriteLine("\t Comment: {0}", comment.CommentText);
                }
            }

        }
    }

运行结果

 

posted on 2016-07-25 11:19  yunxia_云霞  阅读(163)  评论(0编辑  收藏  举报