+6

Query trong web api odata

Trong bài viết này mình cùng các bạn tìm hiểu về những query mà có thể thực hiện từ client sử dụng web odata api. Đây chính là điểm mạnh nhất và sự khác biệt lớn nhất mà mình thấy giữa web odata api và web api thông thường. Chúng ta sẽ tạo một project nhỏ về web odata api để demo và tìm hiểu những câu query nhé.

Tạo database

CREATE DATABASE WebApiOdataTest

CREATE TABLE Category (Id int NOT NULL, Name nvarchar(100) NOT NULL, [Description] nvarchar(255), PRIMARY KEY (Id))

CREATE TABLE Product (Id int NOT NULL, Name nvarchar(100) NOT NULL, Price float, CategoryId int, PRIMARY KEY (id),
FOREIGN KEY (CategoryId) REFERENCES Category(Id))

Tạo project

Từ visual studio, chọn new Project -> ASP.NET Web Application -> MVC empty project và chọn Web API.

create project.png

Tiếp theo, ta sẽ generate ra các model từ database vừa tạo bằng cách tạo ra 1 Entity Data Model.

Right click vào thư mục model, chọn new item -> ADO.NET entity data model, đặt tên là EntitiesModel.

Sau đó chọn connectionString và chọn CodeFirstFromDatabase. Chọn các bảng và Finish.

codefirst_select.png

Bây giờ ta đã có các model. Bước tiếp theo là cài đặt web odata v4 package

Right click vào project và chọn Manage Nuget Packages..., tìm Microsoft.AspNet.OData for OData v4.0, install.

nuget odata package.png

Tạo Product Controller kế thừa từ ODataController

using System.Linq;
using System.Web.Http;
using System.Web.OData;
using WebODataV4.Models;

namespace WebODataV4.Controllers
{
    public class ProductController : ODataController
    {
        readonly EntitiesModel _db = new EntitiesModel();

        [EnableQuery(PageSize = 20)]
        public IHttpActionResult Get()
        {
            return Ok(_db.Product.AsQueryable());
        }

        public IHttpActionResult Get([FromODataUri] int key)
        {
            return Ok(_db.Product.SingleOrDefault(t => t.Id == key));
        }

        protected override void Dispose(bool disposing)
        {
            _db.Dispose();
            base.Dispose(disposing);
        }
    }
}

Tiếp theo config route cho Odata service này. Đơn giản như bên dưới.

using System.Web.Http;
using System.Web.OData.Builder;
using System.Web.OData.Extensions;
using WebODataV4.Models;

namespace WebODataV4
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // Web API configuration and services

            // Web API routes
            config.MapHttpAttributeRoutes();

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );

            config.MapODataServiceRoute("odata", "odata", model: GetModel());

            /* now the default setting for WebAPI OData is:
            client can’t apply $count, $orderby, $select, $top, $expand, $filter in the query, query
            like localhost\odata\Customers?$orderby=Name will failed as BadRequest,
            because all properties are not sort-able by default, this is a breaking change in 6.0.0
            So, we now need to enable OData Model Bound Attributes
            */
            config.Count().Filter().OrderBy().Expand().Select().MaxTop(null);
        }

        public static Microsoft.OData.Edm.IEdmModel GetModel()
        {
            ODataModelBuilder builder = new ODataConventionModelBuilder();

            builder.EntitySet<Product>("Product");
            builder.EntitySet<Category>("Category");

            return builder.GetEdmModel();
        }
    }
}

Bây giờ web service api odata của chúng ta đã có thể sử dụng được. Giờ chỉ cần thêm dữ liệu và test thôi. Hãy dùng POSTMAN và thử test nhé

QUERY

lấy tất cả product: http://localhost:1281/odata/Product

1.png

lấy 1 product: http://localhost:1281/odata/Product(1)

2.png

chỉ lấy thuộc tính Id và name của product http://localhost:1281/odata/Product?$select=Id,Name

3.png

lấy thêm cả object category mà product thuộc về http://localhost:1281/odata/Product?&$expand=Category

4.png

chỉ lấy 2 product đầu tiên http://localhost:1281/odata/Product?$top=2

5.png

chỉ lấy 3 products, bỏ qua 2 product đầu tiên http://localhost:1281/odata/Product?$top=3&$skip=2

6.png

sắp xếp list product trả về theo tên http://localhost:1281/odata/Product?$orderby=Name

7.png

lọc product by Name http://localhost:1281/odata/Product?$filter=Name eq 'No family'

8.png

Đếm số lượng bản ghi. chỉ cần thêm option $count=true http://localhost:1281/odata/Product?$count=true

9.png

Những option query này đương nhiên có thể dùng kết hợp với nhau như: http://localhost:1281/odata/Product?$select=Id,Name&$expand=Category http://localhost:1281/odata/Product?$top=3&$skip=2&$orderby=Name

Như vậy với một số lượng dòng code rất ít và đơn giản, nhưng với web odata api, bạn có thể lấy được dữ liệu theo cách mình muốn một cách rất thuận tiện và dễ dàng nhất.


All rights reserved

Bình luận

Đăng nhập để bình luận
Avatar
@VinhLD
thg 2 26, 2019 2:22 SA

Anh cho em hỏi muốn limit bản ghi http://localhost:1281/odata/Product trong cấu hình thì làm thế nào ạ. Vì khi đặt các param kia thì nó sẽ quét tất cả dữ liệu rồi mới lọc ra theo điều kiện. Nếu api connect đến một DB dữ liệu lớn thì không ổn.

Xem thêm (2)
Avatar
@hongocdoanh
thg 3 12, 2019 2:27 SA

việc tối ưu dữ liệu thì còn tùy thuộc vào cách em truyền các param filter, đương nhiên với lượng data lớn thì em phải limit data trả về bằng PageSize hoặc MaxTop. OData cũng chỉ truyền câu query xuống data rồi lấy dữ liệu về thôi, chứ nó ko load hết dữ liệu lên rồi mới filter data đâu. Nên em có thể tối ưu việc lấy data bằng cách optimize dưới database (như đánh index), đồng thời limit dữ liệu trả về để không quá nhiều.

Avatar

@VinhLD Liên kết hơi muộn nhưng có vẻ là nó liên quan đến bài viết này

Avatar
+6
Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí