簡體   English   中英

如何從我的界面中刪除DbSet?

[英]How to remove DbSet from my interface?

我希望我的界面不專門調出DbSet。 我試圖將它們設置為ICollection和IQueryable ...,但是使用IQueryable,我無法調用“添加”方法,例如_db.Posts.Add(post)。 使用ICollection時,每當我調用Add方法時,它都會跳轉到get語句並返回一個列表,而不是將其作為ORM指令的一部分添加以執行插入查詢。

有任何想法嗎? 我迷路了

我的控制器

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();

    }

然后我們有了界面。 我不明白為什么我需要在這里調出DbSet。 我想收藏嗎? 似乎我正在把事情弄亂,就像在此響應中提到的那樣:
ASP.NET MVC4:IQueryable不包含“添加”的定義

public interface IBlogDb
{


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


    void Save();
}

最后是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


}

如果您接受顯式實現並且不介意實現中多了幾行代碼,則可以輕松地從界面中刪除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; }
}

編輯:我發布了這個答案,然后重新閱讀該問題,然后將其刪除,現在又回來了。 從集合中,這將為您提供所需的“添加/刪除”。 如果要使用其他IQueryable,則可以使用另一個接口和顯式實現對其進行分層。 但是,這很難看。

您真正想要的是使用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());
    }
}

您不應該做自己正在做的事情!

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

然后將其注入您的控制器:

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

然后,在您的方法中,您應該正確處理上下文:

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

    }

}

原因是您不想讓數據庫連接保持打開狀態!

現在您已經正確使用了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);
    }
}

所以IMyService是您的控制器將與之交互的對象,因此它的名稱為接口或協定。 因此,這是您要公開用於處理博客上下文的方法的地方:

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
}

因此,請在您的控制器中執行以下操作:

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