我正在使用NHibernate和Rhinomocks,并且无法测试我想要的内容.我想在不命中数据库的情况下测试以下存储库方法(其中_session作为ISession注入到存储库中):
public class Repository : IRepository
{
(... code snipped for brevity ...)
public T FindBy<T>(Expression<Func<T, bool>> where)
{
return _session.Linq<T>().Where(where).FirstOrDefault();
}
}
Run Code Online (Sandbox Code Playgroud)
我最初的方法是模拟ISession,并在调用Linq时返回IQueryable存根(手动编码).我有一个客户对象的IList,我想在memeory中查询以测试我的Linq查询代码而不会访问db.我不确定这会是什么样子.我是否编写自己的IQueryable实现?如果是这样,有人为这种方法做了这个吗?或者我需要查看其他途径?
谢谢!
我正在尝试规范化任意链.Skip()并.Take()调用单个.Skip()调用,然后是可选的单个.Take()调用.
以下是预期结果的一些示例,但我不确定这些是否正确:
.Skip(5) => .Skip(5)
.Take(7) => .Skip(0).Take(7)
.Skip(5).Skip(7) => .Skip(12)
.Skip(5).Take(7) => .Skip(5).Take(7)
.Take(7).Skip(5) => .Skip(5).Take(2)
.Take(5).Take(7) => .Skip(0).Take(5)
.Skip(5).Skip(7).Skip(11) => .Skip(23)
.Skip(5).Skip(7).Take(11) => .Skip(12).Take(11)
.Skip(5).Take(7).Skip(3) => .Skip(8).Take(4)
.Skip(5).Take(7).Take(3) => .Skip(5).Take(4)
.Take(11).Skip(5).Skip(3) => .Skip(8).Take(3)
.Take(11).Skip(5).Take(7) => .Skip(5).Take(6)
.Take(11).Take(5).Skip(3) => .Skip(3).Take(2)
.Take(11).Take(5).Take(3) => .Skip(0).Take(3)
Run Code Online (Sandbox Code Playgroud)
任何人都可以确认这些是预期的正确结果吗?
这是我从示例中得出的基本算法:
class Foo
{
private int skip;
private int? take;
public Foo Skip(int value)
{
if (value < 0)
value = 0;
this.skip += value;
if (this.take.HasValue) …Run Code Online (Sandbox Code Playgroud) 我有以下虚构的域类:
public class Pony
{
public string Name { get; set; }
public DateTime FoundDate { get; set; }
}
public class Person
{
public ICollection<Pony> Ponies { get; private set; }
public Pony NewestPony
{
get
{
return Ponies
.OrderBy(pony => pony.FoundDate)
.FirstOrDefault();
}
}
}
Run Code Online (Sandbox Code Playgroud)
该NewestPony属性封装了一个域规则,用于确定幸运者找到的最新小马.
我可以使用Enumerable扩展方法使用此属性:
IEnumerable<Person> people = GetPeople();
people.Where(p => p.NewestPony != null);
Run Code Online (Sandbox Code Playgroud)
这很棒.
但是,它people是IQueryableSQL Server(在本例中为NHibernate)的外观,查询必须由查询提供程序处理并转换为SQL.由于数据库中没有物理"NewestPony"列,查询提供程序将阻塞查询.
为了解决这个问题,我可以扩展查询中的属性,将其替换为其get实现:
IEnumerable<Person> people = GetPeople();
person.Where(p
=> p.Ponies.OrderBy(pony => …Run Code Online (Sandbox Code Playgroud) 以下工作完美:
IQueryable<Property> PropertyQuery = PropertyDAO.SearchWithAdditionalParameters(/* elided */);
IQueryable<long> propertyIdQuery = PropertyQuery.Select(p => p.PropertyId);
var relevantFMVs = PropertyDAO.db.FMVHistories.Where(f => propertyIdQuery.Contains(f.PropertyId)).ToList();
Run Code Online (Sandbox Code Playgroud)
但是以下情况爆发了:
IQueryable<Property> PropertyQuery = PropertyDAO.SearchWithAdditionalParameters(/* elided */);
var relevantFMVs = PropertyDAO.db.FMVHistories.Where(f => PropertyQuery.Select(p => p.PropertyId).Contains(f.PropertyId)).ToList();
Run Code Online (Sandbox Code Playgroud)
(请注意,我没有单独创建propertyIdQuery,而只是将变量本身替换为查询本身)
例外是
无法转换类型'System.Linq.IQueryable
1' to type 'System.Linq.IQueryable1'.LINQ to Entities仅支持转换实体数据模型基元类型.
有人可以了解EF(4)在封面下做什么只做第一次查询工作,即使它们表面上是等效的吗?
我知道IQueryable<T>,表达树在幕后做了很多事情,但是如何将中间步骤保存到局部变量会影响结果呢?
编辑
根据请求,这是被调用的完整方法,以及该方法调用的方法:
public IQueryable<Property> BasicSearchFromConstraints(PropertyInvoiceConstraints constraints) {
return ExecuteSearchFromConstraints((dynamic)constraints.PropertyInst, constraints.CompanyNumber, constraints.TaxSubType, constraints.PhaseID, constraints.State, constraints.County, constraints.City, constraints.Jurisdiction);
}
private IQueryable<T> ExecuteSearchFromConstraints<T>(T property, int CompanyNumber, byte SubType, byte PhaseID, string State, string County, string …Run Code Online (Sandbox Code Playgroud) 我偶然发现了下一个问题...我有数据库上下文:
// For support unit testing...
public interface IDbContext : IDisposable
{
IQueryable<Hardware> Hardwares { get; }
IQueryable<ProviderHardware> ProviderHardwares { get; }
}
// Real DbContext (EF 4.0, Code First)
public class PrimaryDbContext : DbContext, IDbContext
{
public DbSet<Hardware> Hardwares { get; set; }
public DbSet<ProviderHardware> ProviderHardwares { get; set; }
IQueryable<Hardware> IDbContext.Hardwares
{ get { return Hardwares; } }
IQueryable<ProviderHardware> IDbContext.ProviderHardwares
{ get { return ProviderHardwares; } }
...
}
Run Code Online (Sandbox Code Playgroud)
我尝试获取ProviderHardwares表中不存在的所有硬件:
var hardwaresRemoved = db.Hardwares.Where(i => (i.IsAvailable == true) …Run Code Online (Sandbox Code Playgroud) 我有一个WebApi方法,它返回一个IQueryable的RavenDB文档.调用者需要知道可能结果的数量(因为实际结果是有限的/分页的).
所以,我的WebApi方法结束时有类似的东西:
HttpContext.Current.Response.AddHeader("Total-Result-Count",
resultsStats.TotalResults.ToString())
Run Code Online (Sandbox Code Playgroud)
不幸的是,这不起作用,因为IQueryable还没有实际执行 - 所以统计数据将是空的.
在查询执行之后,如何推迟 stats响应标头的填充?
[UPDATE]
在控制器操作执行后,我尝试应用ActionFilter来捕获结果......但似乎在实际枚举IQueryable之前调用了ActionFilter ...
public class CountQueryableResultsActionFilter : ActionFilterAttribute
{
public override void OnActionExecuted(HttpActionExecutedContext filterContext)
{
var controllerStats = filterContext.ActionContext.ControllerContext.Controller as IControllerStatistics;
System.Web.HttpContext.Current.Response.AddHeader("Total-Result-Count", controllerStats.TotalResults.ToString());
}
}
Run Code Online (Sandbox Code Playgroud)
如果,我在WebApi方法结束时调用了"IQueryable.ToArray()",那么Linq查询会立即执行,它会生成统计信息,一切正常 - 但这会阻止用户应用自己的OData过滤器等等...
这是我今晚安排的测试.这是为了证明一些不同的东西,但结果并不像我预期的那样.
我在IQueryable上运行10000次随机查询的测试,在测试时我发现如果我在List上做同样的事情,我的测试速度提高了20倍.
见下文.我的CarBrandManager.GetList最初返回一个IQueryable,但现在我首先发出一个ToList(),然后它的速度更快.
谁能告诉我为什么我看到这个巨大的差异?
var sw = new Stopwatch();
sw.Start();
int queries = 10000;
//IQueryable<Model.CarBrand> carBrands = CarBrandManager.GetList(context);
List<Model.CarBrand> carBrands = CarBrandManager.GetList(context).ToList();
Random random = new Random();
int randomChar = 65;
for (int i = 0; i < queries; i++)
{
randomChar = random.Next(65, 90);
Model.CarBrand carBrand = carBrands.Where(x => x.Name.StartsWith(((char)randomChar).ToString())).FirstOrDefault();
}
sw.Stop();
lblStopWatch.Text = String.Format("Queries: {0} Elapsed ticks: {1}", queries, sw.ElapsedTicks);
Run Code Online (Sandbox Code Playgroud) 我正在尝试对某个IQueryable对象进行关键字搜索,但有没有办法在没有先将其转换为列表的情况下执行此操作?
我的代码:
var customers = Customer.IQueryableAll(); // Method returns IQueryable containing all customers.
var customerHolder = new List<Customer>();
foreach(var k in keywords) //keywords = List<string>
{
customerHolder.AddRange(customers.Where(x=>x.FirstName.Contains(k) || x.LastName.Contains(k) || x.CompanyName.Contains(k)).ToList())
}
return customerHolder.Distinct();
Run Code Online (Sandbox Code Playgroud)
如果我想一次显示所有结果,这是有效的,但问题出现在我想要进行分页的地方.在分页之前,该函数仍然会从数据库中获取所有条目,因此它对大型表的效率非常低.(即customerHolder.Skip(5).Take(5);)
有没有办法将foreach搜索部分集成到查询本身?
即.
customers.Where( x => x.Name.Contains(anythingInKeyWords));
Run Code Online (Sandbox Code Playgroud)
编辑:为了进一步澄清,我确实想要保持上面的OR,所以使用多个where子句进行过滤和重新过滤将不起作用.IE浏览器.Bill Job/Bill Gates>搜索Bill Gates应该返回两个条目,因为比尔匹配.
我有一个相当复杂的逻辑,它IQueryable为我生成一个用于从我的数据库返回数据的方法Fluent.NHibernate.
但是,我需要能够将此查询的结果存储回数据库(实际上只是主键,但这是一个副作用)
如何生成基于IQueryable我已经获得SQL 的插入语句,如下面生成的示例所示:
INSERT INTO MySavedResults (Id, FirstName, LastName)
SELECT Id, FirstName, LastName FROM Member
WHERE
FirstName = 'John' and LastName ='Snow' and ...-- more conditions
Run Code Online (Sandbox Code Playgroud) 我有一些类似下面的代码,我想编写方法的单元测试。但是我陷入了异步方法。你能帮我吗 ?
public class Panel
{
public int Id { get; set; }
[Required] public double Latitude { get; set; }
public double Longitude { get; set; }
[Required] public string Serial { get; set; }
public string Brand { get; set; }
}
public class CrossSolarDbContext : DbContext
{
public CrossSolarDbContext()
{
}
public CrossSolarDbContext(DbContextOptions<CrossSolarDbContext> options) : base(options)
{
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
}
}
public interface IGenericRepository<T>
{ …Run Code Online (Sandbox Code Playgroud) c# unit-testing iqueryable entity-framework-6 asp.net-core-2.0
iqueryable ×10
c# ×7
linq ×4
asp.net ×1
c#-4.0 ×1
dbcontext ×1
list ×1
mocking ×1
nhibernate ×1
performance ×1
ravendb ×1
sql ×1
sql-server ×1
unit-testing ×1
wcf-web-api ×1