Sự khác biệt của dịch vụ AddTransient, AddScoped và AddSingleton


938

Tôi muốn thực hiện tiêm phụ thuộc (DI) trong ASP.NET Core. Vì vậy, sau khi thêm mã này vào ConfigureServicesphương thức, cả hai cách đều hoạt động.

Sự khác biệt giữa services.AddTransientservice.AddScopedcác phương thức trong ASP.NET Core là gì?

public void ConfigureServices(IServiceCollection services)
{
    // Add framework services.

    // Add application services.
    services.AddTransient<IEmailSender, AuthMessageSender>();
    services.AddScoped<IEmailSender, AuthMessageSender>();
}

92
@tmg Các tài liệu nói 'Dịch vụ trọn đời thoáng qua được tạo ra mỗi khi chúng được yêu cầu.' và 'Các dịch vụ trọn đời có phạm vi được tạo một lần cho mỗi yêu cầu.' điều đó trừ khi tôi hiểu tiếng Anh yếu hơn tôi nghĩ thực sự có nghĩa chính xác điều tương tự.
Neutrino

70
@tmg tôi biết. Tôi chỉ chỉ ra rằng các tài liệu hoàn toàn không rõ ràng về điểm này, vì vậy việc hướng mọi người đến các tài liệu không hữu ích lắm.
Neutrino

13
@Neutrino, đó là lý do tại sao tôi hỏi câu hỏi này.
Elvin Mammadov

5
Đến bữa tiệc muộn, đọc các bình luận thậm chí muộn hơn, nhưng tôi đã in bài báo đó ra, đọc nó và ghi lại cùng một quan sát ở lề mà bây giờ tôi thấy @Neutrino thực hiện ở đây. Bài báo rất mơ hồ trong việc đưa ra phân tích đó. Ví dụ, rất may, đã ít gây nhầm lẫn.
Wellspring

5
Theo tôi hiểu: Các dịch vụ trọn đời thoáng qua được tạo ra mỗi khi chúng được yêu cầu . Từ được yêu cầu ở đây là ý nghĩa tiếng Anh hàng ngày của việc yêu cầu một cái gì đó, trong trường hợp này là một dịch vụ. Trong khi đó, từ yêu cầu trong một lần theo yêu cầu đề cập đến một yêu cầu HTTP. Nhưng tôi hiểu sự đốt cháy.
Memet Olsen

Câu trả lời:


1653

TL; DR

Các đối tượng thoáng qua luôn khác nhau; một phiên bản mới được cung cấp cho mọi bộ điều khiển và mọi dịch vụ.

Các đối tượng có phạm vi giống nhau trong một yêu cầu, nhưng khác nhau giữa các yêu cầu khác nhau.

Các đối tượng Singleton giống nhau cho mọi đối tượng và mọi yêu cầu.

Để làm rõ hơn, ví dụ này từ tài liệu ASP.NET cho thấy sự khác biệt:

Để chứng minh sự khác biệt giữa các tùy chọn đăng ký trọn đời và đăng ký này, hãy xem xét một giao diện đơn giản đại diện cho một hoặc nhiều tác vụ dưới dạng một thao tác với một mã định danh duy nhất , OperationId. Tùy thuộc vào cách chúng tôi định cấu hình trọn đời cho dịch vụ này, container sẽ cung cấp các phiên bản dịch vụ giống hoặc khác nhau cho lớp yêu cầu. Để làm rõ thời gian tồn tại đang được yêu cầu, chúng tôi sẽ tạo một loại cho mỗi tùy chọn trọn đời:

using System;

namespace DependencyInjectionSample.Interfaces
{
    public interface IOperation
    {
        Guid OperationId { get; }
    }

    public interface IOperationTransient : IOperation
    {
    }

    public interface IOperationScoped : IOperation
    {
    }

    public interface IOperationSingleton : IOperation
    {
    }

    public interface IOperationSingletonInstance : IOperation
    {
    }
}

Chúng tôi triển khai các giao diện này bằng một lớp duy nhất, Operationchấp nhận GUID trong hàm tạo của nó hoặc sử dụng GUID mới nếu không được cung cấp:

using System;
using DependencyInjectionSample.Interfaces;
namespace DependencyInjectionSample.Classes
{
    public class Operation : IOperationTransient, IOperationScoped, IOperationSingleton, IOperationSingletonInstance
    {
        Guid _guid;
        public Operation() : this(Guid.NewGuid())
        {

        }

        public Operation(Guid guid)
        {
            _guid = guid;
        }

        public Guid OperationId => _guid;
    }
}

Tiếp theo, trong ConfigureServicesmỗi loại được thêm vào thùng chứa theo tuổi thọ được đặt tên của nó:

services.AddTransient<IOperationTransient, Operation>();
services.AddScoped<IOperationScoped, Operation>();
services.AddSingleton<IOperationSingleton, Operation>();
services.AddSingleton<IOperationSingletonInstance>(new Operation(Guid.Empty));
services.AddTransient<OperationService, OperationService>();

Lưu ý rằng IOperationSingletonInstancedịch vụ đang sử dụng một phiên bản cụ thể với ID đã biết Guid.Empty, vì vậy sẽ rõ ràng khi loại này được sử dụng. Chúng tôi cũng đã đăng ký một OperationServicetùy thuộc vào từng Operationloại khác, do đó sẽ rõ ràng trong yêu cầu liệu dịch vụ này có nhận được cùng một thể hiện như bộ điều khiển hay loại mới cho từng loại hoạt động hay không. Tất cả các dịch vụ này làm là phơi bày các phụ thuộc của nó dưới dạng các thuộc tính, vì vậy chúng có thể được hiển thị trong dạng xem.

using DependencyInjectionSample.Interfaces;

namespace DependencyInjectionSample.Services
{
    public class OperationService
    {
        public IOperationTransient TransientOperation { get; }
        public IOperationScoped ScopedOperation { get; }
        public IOperationSingleton SingletonOperation { get; }
        public IOperationSingletonInstance SingletonInstanceOperation { get; }

        public OperationService(IOperationTransient transientOperation,
            IOperationScoped scopedOperation,
            IOperationSingleton singletonOperation,
            IOperationSingletonInstance instanceOperation)
        {
            TransientOperation = transientOperation;
            ScopedOperation = scopedOperation;
            SingletonOperation = singletonOperation;
            SingletonInstanceOperation = instanceOperation;
        }
    }
}

Để thể hiện thời gian sống của đối tượng trong và giữa các yêu cầu riêng biệt cho ứng dụng, mẫu bao gồm một OperationsControlleryêu cầu từng loại IOperationcũng như một loại OperationService. Các Indexhành động sau đó hiển thị tất cả các bộ điều khiển và dịch vụ OperationIdgiá trị.

using DependencyInjectionSample.Interfaces;
using DependencyInjectionSample.Services;
using Microsoft.AspNetCore.Mvc;

namespace DependencyInjectionSample.Controllers
{
    public class OperationsController : Controller
    {
        private readonly OperationService _operationService;
        private readonly IOperationTransient _transientOperation;
        private readonly IOperationScoped _scopedOperation;
        private readonly IOperationSingleton _singletonOperation;
        private readonly IOperationSingletonInstance _singletonInstanceOperation;

        public OperationsController(OperationService operationService,
            IOperationTransient transientOperation,
            IOperationScoped scopedOperation,
            IOperationSingleton singletonOperation,
            IOperationSingletonInstance singletonInstanceOperation)
        {
            _operationService = operationService;
            _transientOperation = transientOperation;
            _scopedOperation = scopedOperation;
            _singletonOperation = singletonOperation;
            _singletonInstanceOperation = singletonInstanceOperation;
        }

        public IActionResult Index()
        {
            // ViewBag contains controller-requested services
            ViewBag.Transient = _transientOperation;
            ViewBag.Scoped = _scopedOperation;
            ViewBag.Singleton = _singletonOperation;
            ViewBag.SingletonInstance = _singletonInstanceOperation;

            // Operation service has its own requested services
            ViewBag.Service = _operationService;
            return View();
        }
    }
}

Bây giờ hai yêu cầu riêng biệt được thực hiện cho hành động điều khiển này:

Yêu cầu đầu tiên

Đề nghị thứ hai

Quan sát OperationIdgiá trị nào thay đổi trong một yêu cầu và giữa các yêu cầu.

  • Các đối tượng thoáng qua luôn khác nhau; một phiên bản mới được cung cấp cho mọi bộ điều khiển và mọi dịch vụ.

  • Các đối tượng có phạm vi giống nhau trong một yêu cầu, nhưng khác nhau giữa các yêu cầu khác nhau

  • Các đối tượng Singleton giống nhau cho mọi đối tượng và mọi yêu cầu (bất kể trường hợp có được cung cấp hay không ConfigureServices)


14
Tôi hiểu chức năng của từng người trong số họ, nhưng ai đó có thể giải thích tác động của việc sử dụng cái này thay vì cái kia. Vấn đề gì có thể gây ra nếu không được sử dụng đúng cách hoặc chọn một thay vì khác.
pawan nepal

2
Giả sử bạn đang tạo một đối tượng liên quan đến ngữ cảnh yêu cầu (như người dùng hiện tại) với phạm vi đơn lẻ thì nó sẽ vẫn giữ nguyên thể hiện trên tất cả các yêu cầu http không mong muốn. IOC là tất cả về việc tạo các thể hiện, vì vậy chúng ta cần chỉ định phạm vi của thể hiện được tạo.
akazemis

1
đó là!, tôi đã đề cập đến liên kết ở đầu chủ đề! mã mẫu được sao chép / dán từ tài liệu MS
akazemis

1
cảm ơn. yeah singleton sẽ giống nhau trong suốt ứng dụng bất kể phiên / người dùng. rõ ràng nếu ứng dụng của bạn đang sử dụng kiến ​​trúc microservice và mỗi dịch vụ chạy trong một quy trình riêng biệt, thì đơn sẽ giống nhau trong mỗi quy trình
akazemis

1
Bạn có thể cho chúng tôi một ví dụ về việc sử dụng addTransient được không? bởi vì tôi không tìm thấy bất kỳ tiện ích nào để sử dụng nó trong khi nó sử dụng quá nhiều tài nguyên
Terai

319

Trong tiêm phụ thuộc của .NET, có ba vòng đời chính:

Singleton tạo một thể hiện duy nhất trong suốt ứng dụng. Nó tạo ra thể hiện lần đầu tiên và sử dụng lại cùng một đối tượng trong tất cả các cuộc gọi.

Các dịch vụ trọn đời có phạm vi được tạo một lần cho mỗi yêu cầu trong phạm vi. Nó tương đương với một singleton trong phạm vi hiện tại. Ví dụ, trong MVC, nó tạo một thể hiện cho mỗi yêu cầu HTTP, nhưng nó sử dụng cùng một thể hiện trong các cuộc gọi khác trong cùng một yêu cầu web.

Dịch vụ trọn đời thoáng qua được tạo ra mỗi khi chúng được yêu cầu. Cuộc đời này hoạt động tốt nhất cho các dịch vụ nhẹ, không trạng thái.

Ở đây bạn có thể tìm và ví dụ để thấy sự khác biệt:

ASP.NET 5 MVC6 Dependency Injection trong 6 bước (liên kết lưu trữ web do liên kết chết)

ASP.NET Dependency tiêm sẵn sàng ASP.NET: ASP.NET 5

Và đây là liên kết đến tài liệu chính thức:

Tiêm phụ thuộc vào ASP.NET Core


22
Bạn có thể giải thích tại sao Transient là nhẹ nhất? Tôi nghĩ rằng Transient là công việc nặng nhọc nhất vì nó cần tạo ra một thể hiện mỗi lần cho mỗi lần tiêm.
Chuyên gia muốn là

17
Bạn đúng. Transient không phải là nhẹ nhất, tôi chỉ nói nó phù hợp với các dịch vụ RESTful nhẹ :)
akazemis

3
Vì vậy, trong trường hợp nào chúng ta có thể sử dụng phạm vi và trong ví dụ nhất thời trong bộ điều khiển ví dụ nếu chúng ta đang truy xuất một vài hàng từ cơ sở dữ liệu? Tôi đang cố gắng hiểu kịch bản sử dụng trong phạm vi và tạm thời trong trường hợp này.
Sensei

4
nó thực sự phụ thuộc vào logic bạn mong đợi. Chẳng hạn, nếu đó là một cuộc gọi db duy nhất thì nó thực sự không tạo ra bất kỳ sự khác biệt nào mà bạn đang sử dụng. nhưng nếu bạn gọi db nhiều lần trong cùng một yêu cầu, thì bạn có thể sử dụng vòng đời trong phạm vi, vì nó giữ cùng một đối tượng kho lưu trữ trong bộ nhớ và sử dụng lại nhiều lần trong cùng bối cảnh Yêu cầu http. Trong khi đó tạm thời tạo một đối tượng kho lưu trữ mới nhiều lần (và tiêu tốn nhiều bộ nhớ hơn). Nếu bạn giải thích kịch bản cụ thể của mình, thật dễ dàng để đánh giá cái nào phù hợp hơn.
akazemis

3
Một điểm quan trọng cần làm nổi bật ở đây là Singleton, Scoped và Transient giống như các doills của Nga, một trong những điểm khác. Không thể đảo ngược thứ tự của chúng khi làm tổ, ví dụ. một phạm vi hoặc đơn lẻ không thể được chứa trong Transient, bởi vì chúng ta sẽ kéo dài thời gian sống của cha mẹ đi ngược lại sự ngăn chặn!
DL Narasimhan

34

Transient, scoped và singleton xác định quy trình tạo đối tượng trong ASP.NET MVC core DI khi nhiều đối tượng cùng loại phải được tiêm. Trong trường hợp bạn chưa quen với việc tiêm phụ thuộc, bạn có thể xem video DI IoC này .

Bạn có thể thấy mã trình điều khiển bên dưới mà tôi đã yêu cầu hai trường hợp "IDal" trong hàm tạo. Transient, Scoped và Singleton xác định nếu cùng một thể hiện sẽ được thêm vào "_dal" và "_dal1" hoặc khác nhau.

public class CustomerController : Controller
{
    IDal dal = null;

    public CustomerController(IDal _dal,
                              IDal _dal1)
    {
        dal = _dal;
        // DI of MVC core
        // inversion of control
    }
}

Tạm thời: Trong thoáng qua, các phiên bản đối tượng mới sẽ được đưa vào trong một yêu cầu và phản hồi. Dưới đây là hình ảnh chụp nhanh nơi tôi hiển thị các giá trị GUID.

Nhập mô tả hình ảnh ở đây

Phạm vi: Trong phạm vi, cùng một đối tượng sẽ được đưa vào trong một yêu cầu và phản hồi.

Nhập mô tả hình ảnh ở đây

Singleton: Trong singleton, cùng một đối tượng sẽ được đưa vào trong tất cả các yêu cầu và phản hồi. Trong trường hợp này, một thể hiện toàn cầu của đối tượng sẽ được tạo.

Dưới đây là một sơ đồ đơn giản giải thích trực quan cơ bản ở trên.

Hình ảnh MVC DI

Hình ảnh trên được nhóm SBSS vẽ khi tôi đang tham gia khóa đào tạo ASP.NET MVC ở Mumbai . Xin chân thành cảm ơn đội ngũ SBSS đã tạo ra hình ảnh trên.


9
Đây là lời giải thích phức tạp nhất về dịch vụ tạm thời tôi từng thấy. Transient = Bất cứ khi nào dịch vụ này được giải quyết là tương đương với việc gán biến của bạn new TService. Scoped sẽ lưu trữ lần khởi tạo đầu tiên của nó cho "phạm vi" đó (yêu cầu http trong hầu hết các trường hợp). Singleton sẽ lưu trữ bộ đệm duy nhất trong suốt vòng đời của ứng dụng, Đơn giản như vậy. Các sơ đồ trên là rất phức tạp.
Mardoxx

2
Vì vậy, xin lỗi tôi nghĩ rằng tôi sẽ làm cho nó đơn giản hơn với sơ đồ và mã chụp nhanh :-) Nhưng tôi có được quan điểm của bạn.
Shivprasad Koirala

30
  • Singleton là một ví dụ duy nhất cho vòng đời của miền ứng dụng.
  • Scoped là một ví dụ duy nhất cho thời lượng của yêu cầu phạm vi, có nghĩa là mỗi yêu cầu HTTP trong ASP.NET.
  • Transient là một ví dụ duy nhất cho mỗi yêu cầu .

Thông thường, yêu cầu mã phải được thực hiện thông qua tham số hàm tạo, như trong

public MyConsumingClass(IDependency dependency)

Tôi muốn chỉ ra trong câu trả lời của @ akazemis rằng "dịch vụ" trong bối cảnh DI không ngụ ý các dịch vụ RESTful; dịch vụ là việc thực hiện các phụ thuộc cung cấp chức năng.


16

AddSingleton ()

AddSingleton () tạo một phiên bản duy nhất của dịch vụ khi được yêu cầu lần đầu và sử dụng lại thể hiện đó trong tất cả các nơi cần dịch vụ đó.

AddScoped ()

Trong một dịch vụ phạm vi, với mỗi yêu cầu HTTP, chúng tôi nhận được một phiên bản mới. Tuy nhiên, trong cùng một yêu cầu HTTP, nếu dịch vụ được yêu cầu ở nhiều nơi, như trong chế độ xem và trong bộ điều khiển, thì cùng một thể hiện được cung cấp cho toàn bộ phạm vi của yêu cầu HTTP đó. Nhưng mỗi yêu cầu HTTP mới sẽ nhận được một phiên bản mới của dịch vụ.

AddTransient ()

Với một dịch vụ tạm thời, một phiên bản mới được cung cấp mỗi khi một phiên bản dịch vụ được yêu cầu cho dù đó là trong phạm vi của cùng một yêu cầu HTTP hoặc trên các yêu cầu HTTP khác nhau.


5

Sau khi tìm kiếm một câu trả lời cho câu hỏi này, tôi đã tìm thấy một lời giải thích tuyệt vời với một ví dụ mà tôi muốn chia sẻ với bạn.

Bạn có thể xem video chứng minh sự khác biệt TẠI ĐÂY

Trong ví dụ này, chúng tôi có mã đã cho này:

public interface IEmployeeRepository
{
    IEnumerable<Employee> GetAllEmployees();
    Employee Add(Employee employee);
}

public class Employee
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class MockEmployeeRepository : IEmployeeRepository
{
    private List<Employee> _employeeList;

    public MockEmployeeRepository()
    {
        _employeeList = new List<Employee>()
    {
        new Employee() { Id = 1, Name = "Mary" },
        new Employee() { Id = 2, Name = "John" },
        new Employee() { Id = 3, Name = "Sam" },
    };
    }

    public Employee Add(Employee employee)
    {
        employee.Id = _employeeList.Max(e => e.Id) + 1;
        _employeeList.Add(employee);
        return employee;
    }

    public IEnumerable<Employee> GetAllEmployees()
    {
        return _employeeList;
    }
}

HomeContoder

public class HomeController : Controller
{
    private IEmployeeRepository _employeeRepository;

    public HomeController(IEmployeeRepository employeeRepository)
    {
        _employeeRepository = employeeRepository;
    }

    [HttpGet]
    public ViewResult Create()
    {
        return View();
    }

    [HttpPost]
    public IActionResult Create(Employee employee)
    {
        if (ModelState.IsValid)
        {
            Employee newEmployee = _employeeRepository.Add(employee);
        }

        return View();
    }
}

Tạo chế độ xem

@model Employee
@inject IEmployeeRepository empRepository

<form asp-controller="home" asp-action="create" method="post">
    <div>
        <label asp-for="Name"></label>
        <div>
            <input asp-for="Name">
        </div>
    </div>

    <div>
        <button type="submit">Create</button>
    </div>

    <div>
        Total Employees Count = @empRepository.GetAllEmployees().Count().ToString()
    </div>
</form>

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    services.AddSingleton<IEmployeeRepository, MockEmployeeRepository>();
}

Sao chép-dán mã này và nhấn vào nút tạo trong chế độ xem và chuyển đổi giữa AddSingleton, AddScopedAddTransientbạn sẽ nhận được mỗi lần một kết quả khác nhau có thể giúp bạn hiểu lời giải thích này:

AddSingleton () - Như tên của nó, phương thức AddSingleton () tạo ra một dịch vụ Singleton. Một dịch vụ Singleton được tạo khi nó được yêu cầu lần đầu tiên. Trường hợp tương tự này sau đó được sử dụng bởi tất cả các yêu cầu tiếp theo. Vì vậy, nói chung, một dịch vụ Singleton chỉ được tạo một lần cho mỗi ứng dụng và cá thể đó được sử dụng trong suốt thời gian sử dụng của ứng dụng.

AddTransient () - Phương thức này tạo ra một dịch vụ thoáng qua. Một phiên bản mới của dịch vụ tạm thời được tạo mỗi lần nó được yêu cầu.

AddScoped () - Phương thức này tạo ra một dịch vụ Scoped. Một phiên bản mới của dịch vụ Phạm vi được tạo một lần cho mỗi yêu cầu trong phạm vi. Ví dụ: trong một ứng dụng web, nó tạo 1 thể hiện cho mỗi yêu cầu http nhưng sử dụng cùng một thể hiện trong các cuộc gọi khác trong cùng một yêu cầu web đó.


2

Cái nào dùng

Tạm thời

  • vì chúng được tạo ra mỗi lần chúng sẽ sử dụng nhiều bộ nhớ & Tài nguyên hơn và có thể có tác động tiêu cực đến hiệu suất
  • sử dụng điều này cho các dịch vụ nhẹ với ít hoặc không có trạng thái .

Phạm vi

  • tùy chọn tốt hơn khi bạn muốn duy trì trạng thái trong một yêu cầu.

Người độc thân

  • rò rỉ bộ nhớ trong các dịch vụ này sẽ tích tụ theo thời gian.
  • cũng bộ nhớ hiệu quả khi chúng được tạo ra một lần nữa được sử dụng ở mọi nơi.

Sử dụng Singletons nơi bạn cần duy trì trạng thái rộng ứng dụng. Cấu hình ứng dụng hoặc tham số, Dịch vụ ghi nhật ký, lưu trữ dữ liệu là một số ví dụ mà bạn có thể sử dụng singletons.

Tiêm dịch vụ với nhiều kiếp khác nhau

  1. Không bao giờ tiêm dịch vụ Scoped & Transient vào dịch vụ Singleton. (Điều này có hiệu quả chuyển đổi dịch vụ tạm thời hoặc phạm vi thành đơn lẻ.)
  2. Không bao giờ tiêm dịch vụ tạm thời vào dịch vụ có phạm vi (Điều này chuyển đổi dịch vụ tạm thời thành phạm vi.)

Đây là câu trả lời tốt nhất. Tôi thích một phần mà bạn đưa ra ví dụ. Không quá khó để hiểu cách họ làm việc. Thật khó khăn hơn để nghĩ dịch vụ nào sẽ được đặt ở đâu và làm thế nào và khi nào bộ nhớ được làm sạch chúng. Sẽ thật tuyệt nếu bạn giải thích thêm về điều đó.
valentasm

1

Như được mô tả ở đây (liên kết này rất hữu ích) với một ví dụ,

Ánh xạ giữa giao diện và loại cụ thể này xác định rằng mỗi khi bạn yêu cầu một loại IContryService, bạn sẽ nhận được một phiên bản mới của CountryService. Đây là những gì thoáng qua có nghĩa là trong trường hợp này. Bạn cũng có thể thêm ánh xạ singleton (sử dụng AddSingleton) và ánh xạ có phạm vi (sử dụng AddScoped). Phạm vi trong trường hợp này có nghĩa là phạm vi yêu cầu HTTP, cũng có nghĩa là nó là một đơn trong khi yêu cầu hiện tại đang chạy. Bạn cũng có thể thêm một thể hiện hiện có vào bộ chứa DI bằng phương thức AddInstance. Đây là những cách gần như hoàn chỉnh để đăng ký vào IServiceCollection


1

Sự khác biệt giữa AddSingleton so với AddScoped so với AddTransient

Đăng ký dịch vụ

ASP.NET core cung cấp 3 phương thức sau để đăng ký dịch vụ với thùng chứa phụ thuộc. Phương pháp mà chúng tôi sử dụng xác định thời gian tồn tại của dịch vụ đã đăng ký.

AddSingleton () - Như tên của nó, phương thức AddSingleton () tạo ra một dịch vụ Singleton. Một dịch vụ Singleton được tạo khi nó được yêu cầu lần đầu tiên. Trường hợp tương tự này sau đó được sử dụng bởi tất cả các yêu cầu tiếp theo. Vì vậy, nói chung, một dịch vụ Singleton chỉ được tạo một lần cho mỗi ứng dụng và cá thể đó được sử dụng trong suốt thời gian sử dụng của ứng dụng.

AddTransient () - Phương thức này tạo ra một dịch vụ thoáng qua. Một phiên bản mới của dịch vụ tạm thời được tạo mỗi lần nó được yêu cầu.

AddScoped () - Phương thức này tạo ra một dịch vụ Scoped. Một phiên bản mới của dịch vụ Phạm vi được tạo một lần cho mỗi yêu cầu trong phạm vi. Ví dụ: trong một ứng dụng web, nó tạo 1 thể hiện cho mỗi yêu cầu http nhưng sử dụng cùng một thể hiện trong các cuộc gọi khác trong cùng một yêu cầu web đó.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.