简体   繁体   English

如何从我的界面中删除DbSet?

[英]How to remove DbSet from my interface?

I would prefer that my interface didn't call out DbSet exclusively. 我希望我的界面不专门调出DbSet。 I was trying to make them into ICollection and IQueryable...but with IQueryable I couldn't call the "Add" method such as _db.Posts.Add(post). 我试图将它们设置为ICollection和IQueryable ...,但是使用IQueryable,我无法调用“添加”方法,例如_db.Posts.Add(post)。 With ICollection whenever I called the Add method it would jump to the get statement and return a list instead of adding it as part of the ORM instructions to do an insert Query. 使用ICollection时,每当我调用Add方法时,它都会跳转到get语句并返回一个列表,而不是将其作为ORM指令的一部分添加以执行插入查询。

Any ideas? 有任何想法吗? I'm lost 我迷路了

My controller 我的控制器

private readonly IBlogDb _db;

    public PostsController(IBlogDb db)
    {
        _db = db;
    }

public ActionResult Update(int? id, string title, string body, DateTime date, string tags)
    {



        if (!IsAdmin)
        {
            RedirectToAction("Index");
        }
        if (ModelState.IsValid)
        {
            Post post = GetPost(id);
            post.Title = title;
            post.Body = body;
            post.Date = date;
            post.Tags.Clear();

            tags = tags ?? string.Empty;
            string[] tagNames = tags.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

            foreach (string tagName in tagNames)
            {
                post.Tags.Add(GetTag(tagName));
            }

            if (!id.HasValue || id == 0)
            {
                _db.Posts.Add(post);
                _db.Save();

            }
            _db.Save();

            return RedirectToAction("Details", new { id = post.Id });
        }
        return View();

    }

Then we have the interface. 然后我们有了界面。 I don't get why I need to call out the DbSet here. 我不明白为什么我需要在这里调出DbSet。 I'd like to make it a collection? 我想收藏吗? Seems like I'm cluttering things up like was mentioned in this response: 似乎我正在把事情弄乱,就像在此响应中提到的那样:
ASP.NET MVC4: IQueryable does not contain a definition for 'Add' ASP.NET MVC4:IQueryable不包含“添加”的定义

public interface IBlogDb
{


    DbSet<Post> Posts { get; }
    DbSet<Tag> Tags { get; }


    void Save();
}

Finally the DbContext class 最后是DbContext类

public class BlogDb : DbContext, IBlogDb
{
    public BlogDb()
        : base("DefaultConnection")
    {

    }
    public DbSet<Post> Posts { get; set; }
    public DbSet<Tag> Tags { get; set; }

    void IBlogDb.Save()
    {
        SaveChanges();
    }


    public DbSet<Comment> Comments { get; set; }
    public DbSet<Administrator> Administrators { get; set; }


    //Implementing IBlogDb


}

You can easily remove DbSet from your interface if you embrace explicit implementation and don't mind a few extra lines of code in the implementation: 如果您接受显式实现并且不介意实现中多了几行代码,则可以轻松地从界面中删除DbSet:

public interface IMyDbContext
{
    ICollection<Customer> Customers { get; }
}

public class MyDbContext : IMyContext
{
    ICollection<Customer> IMyContext.Customers { get { return (ICollection<Customer>)Customers; } }

    public DbSet<Customer> Customers { get; set; }
}

EDIT: I posted this answer, then reread the question, then deleted it, and now it's back. 编辑:我发布了这个答案,然后重新阅读该问题,然后将其删除,现在又回来了。 This will get you what you need as far as Add/Remove from the collection. 从集合中,这将为您提供所需的“添加/删除”。 If you want an additional IQueryable instead, you can layer it with another interface and explicit implementation. 如果要使用其他IQueryable,则可以使用另一个接口和显式实现对其进行分层。 However, this gets ugly. 但是,这很难看。

What you really want is to use an IDbSet and create a class, such as this replacement for DbSet 您真正想要的是使用IDbSet并创建一个类,例如DbSet的替代品

public class MemoryDbSet<TEntity> : DbSet<TEntity>, IQueryable,
    IEnumerable<TEntity>, IDbAsyncEnumerable<TEntity>
    where TEntity : class
{
    private readonly Func<TEntity, object[], bool> _findSelector;
    private readonly ObservableCollection<TEntity> _data;
    private readonly IQueryable _query;

    public MemoryDbSet(Func<TEntity, object[], bool> findSelector)
    {
        _findSelector = findSelector;
        _data = new ObservableCollection<TEntity>();
        _query = _data.AsQueryable();
    }

    public override TEntity Find(params object[] keyValues)
    {
        return _data.SingleOrDefault(item => _findSelector(item, keyValues));
    }

    public override TEntity Add(TEntity item)
    {
        _data.Add(item);
        return item;
    }

    public override TEntity Remove(TEntity item)
    {
        _data.Remove(item);
        return item;
    }

    public override TEntity Attach(TEntity item)
    {
        _data.Add(item);
        return item;
    }

    public override TEntity Create()
    {
        return Activator.CreateInstance<TEntity>();
    }

    public override TDerivedEntity Create<TDerivedEntity>()
    {
        return Activator.CreateInstance<TDerivedEntity>();
    }

    public override ObservableCollection<TEntity> Local
    {
        get { return _data; }
    }

    Type IQueryable.ElementType
    {
        get { return _query.ElementType; }
    }

    Expression IQueryable.Expression
    {
        get { return _query.Expression; }
    }

    IQueryProvider IQueryable.Provider
    {
        get
        {
            return new MemoryDbAsyncQueryProvider<TEntity>(_query.Provider);
        }
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return _data.GetEnumerator();
    }

    IEnumerator<TEntity> IEnumerable<TEntity>.GetEnumerator()
    {
        return _data.GetEnumerator();
    }

    IDbAsyncEnumerator<TEntity> IDbAsyncEnumerable<TEntity>.
        GetAsyncEnumerator()
    {
        return new MemoryDbAsyncEnumerator<TEntity>(_data.GetEnumerator());
    }
}

You shouldn't be doing what your are doing! 您不应该做自己正在做的事情!

public class DbContextFactory : IDbContextFactory<BlogDb>
{
    public BlogDb Create() 
    {
        return new BlogDb();
    }
}

Then inject this into your controller: 然后将其注入您的控制器:

public class MyController : Controller
{
    private readonly IDbContextFactory<BlogDb> blogContextFactory;
    public MyController(IDbContextFactory<BlogDb> blogContextFactory)
    {
        this.blogContextFactory = blogContextFactory;
    }
}

Then in your method you should be disposing of the context properly: 然后,在您的方法中,您应该正确处理上下文:

public ActionResult SaveRecord(FormCollection formStuff)
{
    if (ModelState.IsValid)
    {
         try
         {
             using ( var context = blogContextFactory.Create())
             {
                 // do you stuff here!
             }
         }

    }

}

The reason being is that you don't want to be leaving a database connection open! 原因是您不想让数据库连接保持打开状态!

Now that you are using the context correctly, you can create yourself a service that exposes the method, in that service you can hide the context implementation. 现在您已经正确使用了context ,可以为自己创建一个公开该方法的服务,在该服务中您可以隐藏上下文实现。

public class MyService : IMyService
{
    private readonly IDbContextFactory<BlogDb> blogContextFactory;
    public MyService(IDbContextFactory<BlogDb> blogContextFactory)
    {
        this.blogContextFactory = blogContextFactory;
    }

    public void CreateBlog(FormCollection formStuff) {};

    public void UpdateBlog() {};

    public IQueryable<Blog> Retrieve(Func<Blog, bool> predicate)
    {
        return this.context.Blogs.Where(predicate);
    }
}

So IMyService is what your controller will interact with, hence its name as an interface or contract. 所以IMyService是您的控制器将与之交互的对象,因此它的名称为接口或协定。 So this is where you want to expose your methods for manipulating the blog context: 因此,这是您要公开用于处理博客上下文的方法的地方:

public interface IMyService
{
     void CreateBlog(Blog blog); // you can have what ever passed through to the create, a viewModel, a DTO model or the Domain model. Personally I choose the DTO model.

     void UpdateBlog(Blog blog);

     void DeleteBlog(Guid id);

     IQueryable<Blog> RetreiveBlogs(Func<Blog, bool> predicate); // the predicate allows you to do a quick query if you want to
}

so in your controller do this instead: 因此,请在您的控制器中执行以下操作:

public class MyController : Controller
{
    private readonly IMyService blogService;
    public MyController(IMyService blogService)
    {
        this.blogService= blogService;
    }

    public ActionResult SaveRecord(FormCollection formStuff)
    {
        if (ModelState.IsValid)
        {
             try
             {
                 this.blogService.CreateBlog(formStuff);
             }

        }

     }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM