模拟 dbcontext 中的自动递增主键
Auto increment primary key in mocked db context
有谁知道如何在我的模拟数据库上下文中自动增加主键?我正在对一种方法进行单元测试,当我想将两个项目添加到我的模拟数据库上下文时,我收到一条错误消息“已添加具有相同键的项目”。所以我应该找到一种方法来设置我的数据库上下文模拟,这样每次添加一个项目时,它都会添加不同的主键。
这是我的服务方法 class:
public async Task<ProductDTO> CreateProduct(ProductDTO dto)
{
foreach (var i in dto.Products)
{
if (i.ProductId == 0)
{
// New product
var product = Product.CreateMyProductDto(i);
_db.Products.Add(product);
}
}
// rest of the code …
}
所以在这里我们查看 dto.products,如果任何产品的 productId 等于零,那么我们通过调用 Product.CreateMyProductDto 函数创建我们的产品并将其添加到产品 table。在下面的单元测试中,我有两个 productId = 0 的产品,因此应该将它们添加到 Products table 但由于主键,我在添加第二个产品时出错。
[Fact]
public async Task TestForCreateProduct()
{
//Arrange
List<Product> products = new List<Product>();
Product product1 = new Poduct()
{
ProductId = 0
};
Product product2 = new Poduct()
{
ProductId = 0
};
// add to the products list
products.Add(product1);
products.Add(product2);
ProductDTo dto = new ProductDTO()
{
Products = products
};
// create mock
DbContextMock<MyContext> context_Moq = new DbContextMock<MyContext>(DummyOptions);
// set up mock
context_Moq.CreateDbSetMock(x => x.Products, new[]
{
new Product { EntityId = 1, Name = "product1"},
new Product { EntityId = 2, Name = "product2"},
new Product { EntityId = 3, Name = "product3"}
});
var service = new myService(context_Moq.Object);
// Act
var result = await service.CreateProduct(dto);
// Assert
Assert.Equal(5, context_Moq.Object.Products.Count());
}
我正在使用 .NET core3 所以谁能帮我解决这个错误?我需要在我的模拟数据库上下文中有自动递增主键。
我终于可以解决这个问题了。正如您在下面看到的,EntityId 是我的 Product class 中的主键,我使用了 [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] 属性以使 EntityId[=11= 具有自动递增标识列]
public class Product
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long EntityId { get; set; }
// rest of the code
}
在这种情况下,项目被添加到我模拟的 dbContext 中,EntityIds 从 1 开始。
假设您使用一个 EntityId 为 1 的项目设置 dbContext。然后
您调用 Add 函数将产品添加到 Products table 您将收到相同的错误,因为它尝试添加 EntityId 1 已经在您的模拟 dbContext 中的产品。所以具有相同键的项目不能在数据库中。
在 2 种情况下,您不能将此属性用作主键:
- 如果你的主键是外键
- 当你的主键上有 ValueGeneratedNever() 方法时
有谁知道如何在我的模拟数据库上下文中自动增加主键?我正在对一种方法进行单元测试,当我想将两个项目添加到我的模拟数据库上下文时,我收到一条错误消息“已添加具有相同键的项目”。所以我应该找到一种方法来设置我的数据库上下文模拟,这样每次添加一个项目时,它都会添加不同的主键。 这是我的服务方法 class:
public async Task<ProductDTO> CreateProduct(ProductDTO dto)
{
foreach (var i in dto.Products)
{
if (i.ProductId == 0)
{
// New product
var product = Product.CreateMyProductDto(i);
_db.Products.Add(product);
}
}
// rest of the code …
}
所以在这里我们查看 dto.products,如果任何产品的 productId 等于零,那么我们通过调用 Product.CreateMyProductDto 函数创建我们的产品并将其添加到产品 table。在下面的单元测试中,我有两个 productId = 0 的产品,因此应该将它们添加到 Products table 但由于主键,我在添加第二个产品时出错。
[Fact]
public async Task TestForCreateProduct()
{
//Arrange
List<Product> products = new List<Product>();
Product product1 = new Poduct()
{
ProductId = 0
};
Product product2 = new Poduct()
{
ProductId = 0
};
// add to the products list
products.Add(product1);
products.Add(product2);
ProductDTo dto = new ProductDTO()
{
Products = products
};
// create mock
DbContextMock<MyContext> context_Moq = new DbContextMock<MyContext>(DummyOptions);
// set up mock
context_Moq.CreateDbSetMock(x => x.Products, new[]
{
new Product { EntityId = 1, Name = "product1"},
new Product { EntityId = 2, Name = "product2"},
new Product { EntityId = 3, Name = "product3"}
});
var service = new myService(context_Moq.Object);
// Act
var result = await service.CreateProduct(dto);
// Assert
Assert.Equal(5, context_Moq.Object.Products.Count());
}
我正在使用 .NET core3 所以谁能帮我解决这个错误?我需要在我的模拟数据库上下文中有自动递增主键。
我终于可以解决这个问题了。正如您在下面看到的,EntityId 是我的 Product class 中的主键,我使用了 [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] 属性以使 EntityId[=11= 具有自动递增标识列]
public class Product
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long EntityId { get; set; }
// rest of the code
}
在这种情况下,项目被添加到我模拟的 dbContext 中,EntityIds 从 1 开始。 假设您使用一个 EntityId 为 1 的项目设置 dbContext。然后 您调用 Add 函数将产品添加到 Products table 您将收到相同的错误,因为它尝试添加 EntityId 1 已经在您的模拟 dbContext 中的产品。所以具有相同键的项目不能在数据库中。 在 2 种情况下,您不能将此属性用作主键:
- 如果你的主键是外键
- 当你的主键上有 ValueGeneratedNever() 方法时