c# – ASP.NET Core中AsNoTracking的模拟或更好的解决方法
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了c# – ASP.NET Core中AsNoTracking的模拟或更好的解决方法,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含5582字,纯文字阅读大概需要8分钟。
内容图文
![c# – ASP.NET Core中AsNoTracking的模拟或更好的解决方法](/upload/InfoBanner/zyjiaocheng/782/0e25b5d1fd54483a9109f096c61f433a.jpg)
你如何模拟AsNoTracking或者是否有更好的解决方法来解决这个问题?
例:
public class MyContext : MyContextBase
{
// Constructor
public MyContext(DbContextOptions<MyContext> options) : base(options)
{
}
// Public properties
public DbSet<MyList> MyLists{ get; set; }
}
public class MyList
{
public string Id { get; set; }
public string Email { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public bool Blocked { get; set; }
}
public class MyController : MyControllerBase
{
private MyContext ContactContext = this.ServiceProvider.GetService<MyContext>();
public MyController(IServiceProvider serviceProvider) : base(serviceProvider)
{
}
private bool isContact(string firstName, string lastName)
{
try
{
var list = this
.ContactContext
.MyLists
.AsNoTracking() // !!!Here it explodes!!!
.FirstOrDefault(entity => entity.FirstName == firstName && entity.LastName == lastName);
return list != null;
}
catch (Exception exception)
{
throws Exception;
}
return false;
}
}
我的测试:
using Moq;
using Xunit;
[Fact]
[Trait("Category", "Controller")]
public void Test()
{
string firstName = "Bob";
string lastName = "Baumeister";
// Creating a list with the expectad data
var fakeContacts = new MyList[]
{
new MyList() { FirstName = "Ted", LastName = "Teddy" },
new MyList() { PartnerId = "Bob", Email = "Baumeister" }
};
// Mocking the DbSet<MyList>
var dbSet = CreateMockSet(fakeContacts.AsQueryable());
// Setting the mocked dbSet in ContactContext
ContactContext contactContext = new ContactContext(new DbContextOptions<ContactContext>())
{
MyLists = dbSet.Object
};
// Mocking ServiceProvider
serviceProvider
.Setup(s => s.GetService(typeof(ContactContext)))
.Returns(contactContext);
// Creating a controller
var controller = new ContactController(serviceProvider.Object);
// Act
bool result = controller.isContact(firstName, lastName)
// Assert
Assert.True(result);
}
private Mock<DbSet<T>> CreateMockSet<T>(IQueryable<T> data)
where T : class
{
var queryableData = data.AsQueryable();
var mockSet = new Mock<DbSet<T>>();
mockSet.As<IQueryable<T>>().Setup(m => m.Provider)
.Returns(queryableData.Provider);
mockSet.As<IQueryable<T>>().Setup(m => m.Expression)
.Returns(queryableData.Expression);
mockSet.As<IQueryable<T>>().Setup(m => m.ElementType)
.Returns(queryableData.ElementType);
mockSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator())
.Returns(queryableData.GetEnumerator());
return mockSet;
}
每次运行此测试时,AsNoTracking()中的isContact(String firstName,String lastName)抛出的异常是:
Exception.Message:
There is no method ‘AsNoTracking’ on type
‘Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions’
that matches the specified arguments
Exception.StackTrace:
at System.Linq.EnumerableRewriter.FindMethod(Type type, String name, ReadOnlyCollection'1 args, Type[] typeArgs)
at System.Linq.EnumerableRewriter.VisitMethodCall(MethodCallExpression m)
at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at System.Linq.EnumerableQuery'1.GetEnumerator()
at System.Linq.EnumerableQuery'1.System.Collections.Generic.IEnumerable<T>.GetEnumerator()
at My.Package.Contact.Controller.MyController.isContact(String firstName, String lastName) in C:\Users\source\repos\src\My.Package\My.Package.Contact\Controller\MyController.cs:line 31
我的尝试:
试图像stackoverflow: mock-asnotracking-entity-framework中建议的那样模拟AsNoTracking:
mockSet.As<IQueryable<T>>().Setup(m => m.AsNoTracking<T>())
.Returns(mockSet.Object);
在System.NotSupportedException中导致ASP.NET Core:
‘Invalid setup on an extension method: m => m.AsNoTracking()’
mockSet.Setup(m => m.AsNoTracking())
.Returns(mockSet.Object);
在AtNoTracking()上更好地了解Microsoft.EntityFrameworkCore EntityFrameworkQueryableExtensions EntityFrameworkCore EntityFrameworkQueryableExtensions.cs之后:
public static IQueryable<TEntity> AsNoTracking<TEntity>(
[NotNull] this IQueryable<TEntity> source)
where TEntity : class
{
Check.NotNull(source, nameof(source));
return
source.Provider is EntityQueryProvider
? source.Provider.CreateQuery<TEntity>(
Expression.Call(
instance: null,
method: AsNoTrackingMethodInfo.MakeGenericMethod(typeof(TEntity)),
arguments: source.Expression))
: source;
}
由于模拟的DbSet<>我在测试期间提供,提供者是IQueryable函数AsNoTracking应返回输入源,因为“source.Provider is EntityQueryProvider”为false.
我唯一检查不到的是Check.NotNull(source,nameof(source));既然我找不到它的作用?如果有人有解释或代码显示它的作用我会很感激,如果你可以与我分享.
解决方法:
我在互联网上找到的唯一解决方法是来自线程https://github.com/aspnet/EntityFrameworkCore/issues/7937中的@cdwaddell,他基本上编写了自己的门控版AsNoTracking().使用变通方法可以获得成功,但我不想实现它,因为它似乎没有检查什么?
public static class QueryableExtensions
{
public static IQueryable<T> AsGatedNoTracking<T>(this IQueryable<T> source) where T : class
{
if (source.Provider is EntityQueryProvider)
return source.AsNoTracking<T>();
return source;
}
}
所以,我的问题:
>我的解决方法是测试这样的东西的唯一方法吗?
>有可能模拟这个吗?
> Check.NotNull是什么(来源,名称(来源));在
AsNoTracking()呢?
解决方法:
不要模拟DataContext.
DataContext是访问层的实现细节. Entity Framework Core提供了两种选项,用于在没有实际数据库的情况下使用DataContext依赖项编写测试.
内存数据库 – Testing with InMemory
SQLite in-memory – Testing with SQLite
为什么你不应该模拟DataContext?
只是因为使用模拟的DataContext,您将仅测试按预期顺序调用的方法.
相反,在测试中,您应该测试代码的行为,返回值,更改状态(数据库更新).
测试行为时,您将能够重构/优化代码,而无需为代码中的每个更改重写测试.
如果内存中测试没有提供所需的行为 – 根据实际数据库测试代码.
内容总结
以上是互联网集市为您收集整理的c# – ASP.NET Core中AsNoTracking的模拟或更好的解决方法全部内容,希望文章能够帮你解决c# – ASP.NET Core中AsNoTracking的模拟或更好的解决方法所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。