ormlite servicestack 为什么Linq(Expression<;Func<;T,bool>;)在泛型类中生成不正确的Where子句?
我有一个用于参考数据项的简单界面:ormlite servicestack 为什么Linq(Expression<;Func<;T,bool>;)在泛型类中生成不正确的Where子句?,ormlite-servicestack,ormlite Servicestack,我有一个用于参考数据项的简单界面: public interface IReferenceItem { int Id { get; set; } string Name { get; set; } } 我希望能够有一个ReferenceItemRepository,其中T:ireReferenceItem能够从数据库中选择任何这样的项目,如下所示: T item = db.Select<T>(s => s.Name == item.Name).FirstNon
public interface IReferenceItem
{
int Id { get; set; }
string Name { get; set; }
}
我希望能够有一个ReferenceItemRepository,其中T:ireReferenceItem
能够从数据库中选择任何这样的项目,如下所示:
T item = db.Select<T>(s => s.Name == item.Name).FirstNonDefault<T>();
SELECT "MarketId" ,"Name"
FROM "Market"
WHERE ("Name" = "Name")
因此,它正确地解析了表及其列的名称,但是Where子句变成了“name”=“name”,这导致它返回该表中的所有行
如果我对MarketRepository
非泛型类做同样的事情:
Market item = db.Select<Market>(s => s.Name == item.Name).FirstNonDefault<Market>();
这是ServiceStack.OrmLite中的一个bug(我用3.9.49测试过),还是我做错了什么,或者这在OrmLite的实现中是不可能的
编辑:
这似乎是一个特定于Linq表达式使用的问题;如果我将该语句切换为以下内容,则它将正常工作:
T item = db.QuerySingle<T>("Name = @name", new { Name = item.Name });
请注意,您需要在该表中有多个项才能显示故障,并且您要查找的记录必须不是查询所有记录时返回的第一个记录;否则,您将完全出于偶然而检索到您要查找的对象。我还没有测试选择方法,我使用了SelectParam,而且一切都很正常。下面我将我的通用存储库模式与OrmLite放在一起(也许它会对您有所帮助)——它与规范模式配合使用效果很好
public class GenericRepository<T> : IRepository<T>
where T : class, new()
{
private readonly IDbConnectionFactory dbConnectionFactory;
public GenericRepository(IDbConnectionFactory dbConnectionFactory)
{
this.dbConnectionFactory = dbConnectionFactory;
}
public IEnumerable<T> FindAll()
{
return dbConnectionFactory.OpenDbConnection().Select<T>();
}
public IEnumerable<T> FindBy(Expression<Func<T, bool>> predicate)
{
return dbConnectionFactory.OpenDbConnection().SelectParam<T>(predicate);
}
public T FindById(int id)
{
return dbConnectionFactory.OpenDbConnection().GetById<T>(id);
}
public void Update(T entity)
{
dbConnectionFactory.OpenDbConnection().UpdateParam(entity);
}
public void Remove(T entity)
{
dbConnectionFactory.OpenDbConnection().Delete(entity);
}
public T FirstOrDefault(Expression<Func<T, bool>> predicate)
{
return dbConnectionFactory.OpenDbConnection().FirstOrDefault(predicate);
}
public void Insert(T entity)
{
dbConnectionFactory.OpenDbConnection().InsertParam(entity);
}
公共类GenericRepository:IRepository
其中T:class,new()
{
私有只读IDbConnectionFactory dbConnectionFactory;
公共通用存储库(IDbConnectionFactory dbConnectionFactory)
{
this.dbConnectionFactory=dbConnectionFactory;
}
公共IEnumerable FindAll()
{
返回dbConnectionFactory.OpenDbConnection().Select();
}
公共IEnumerable FindBy(表达式谓词)
{
返回dbConnectionFactory.OpenDbConnection().SelectParam(谓词);
}
公共T FindById(int id)
{
返回dbConnectionFactory.OpenDbConnection().GetById(id);
}
公共无效更新(T实体)
{
dbConnectionFactory.OpenDbConnection().UpdateParam(实体);
}
公共无效删除(T实体)
{
dbConnectionFactory.OpenDbConnection().Delete(实体);
}
公共T FirstOrDefault(表达式谓词)
{
返回dbConnectionFactory.OpenDbConnection().FirstOrDefault(谓词);
}
公共无效插入(T实体)
{
dbConnectionFactory.OpenDbConnection().InsertParam(实体);
}
编辑: 好的,我举了个例子。代码并不完美,但我只有10分钟的休息时间。 如果要执行此代码,请执行以下操作:1)创建控制台应用程序项目2)添加对ServiceStack.OrmLite的引用-我使用了nuget,有3.9.49.0版本。我希望它能帮助您
class Program
{
static void Main(string[] args)
{
//connection
var dbFactory = new OrmLiteConnectionFactory(@"Server=.\dev;Database=survey;Trusted_Connection=True;", SqlServerDialect.Provider);
//open connection
IDbConnection db = dbFactory.OpenDbConnection();
db.DropAndCreateTable<Market>();
//create item
var newMarket = new Market() { Id = 1, Name = "Shop", LongName = "Big Shop" };
//add item to database
db.InsertParam<Market>(newMarket);
//retrive using standard way
Console.WriteLine("Standard way");
ShowResult(db.Select<Market>(x => x.Name == "Shop"));
//retrive using generic repository with passing predicate to repository method
Console.WriteLine("Generic repository with passing predicate");
var genericRepository = new GenericRepository<Market>(dbFactory);
ShowResult(genericRepository.FindBy(x => x.Name == "Shop"));
//retrive using generic repository with passing specyfic value to repository method
Console.WriteLine("Generic repository with passing specyfic value to repository method");
var genericRepositoryWithHardcodedStatments = new GenericRepositoryWithHardcodedStatments<Market>(dbFactory);
ShowResult(genericRepositoryWithHardcodedStatments.Find("Shop"));
Console.WriteLine("Generic repository with passing T object to repository method");
var genericRepositoryWithPassingT = new GenericRepositoryWithPassingT<Market>(dbFactory);
ShowResult(genericRepositoryWithPassingT.Find(new Market()
{
Name = "shop"
}));
}
private static void ShowResult(IEnumerable<Market> markets)
{
foreach (var market in markets)
{
Console.WriteLine(value: string.Format("{0} - {1} - {2}", market.Id, market.Name, market.LongName));
}
}
}
public class GenericRepository<T> where T : class, new()
{
private readonly IDbConnectionFactory dbConnectionFactory;
public GenericRepository(IDbConnectionFactory dbConnectionFactory)
{
this.dbConnectionFactory = dbConnectionFactory;
}
public IEnumerable<T> FindBy(Expression<Func<T, bool>> predicate)
{
return dbConnectionFactory.OpenDbConnection().SelectParam<T>(predicate);
}
}
public class GenericRepositoryWithHardcodedStatments<T> where T : IReferenceItem, new()
{
private readonly IDbConnectionFactory dbConnectionFactory;
public GenericRepositoryWithHardcodedStatments(IDbConnectionFactory dbConnectionFactory)
{
this.dbConnectionFactory = dbConnectionFactory;
}
public IEnumerable<T> Find(string name)
{
return dbConnectionFactory.OpenDbConnection().SelectParam<T>(x => x.Name == name);
}
}
public class GenericRepositoryWithPassingT<T> where T : IReferenceItem, new()
{
private readonly IDbConnectionFactory dbConnectionFactory;
public GenericRepositoryWithPassingT(IDbConnectionFactory dbConnectionFactory)
{
this.dbConnectionFactory = dbConnectionFactory;
}
public IEnumerable<T> Find(T item)
{
return dbConnectionFactory.OpenDbConnection().SelectParam<T>(x => x.Name == item.Name);
}
}
public interface IReferenceItem
{
int Id { get; set; }
string Name { get; set; }
}
public class Market : IReferenceItem
{
public int Id { get; set; }
public string Name { get; set; }
public string LongName { get; set; }
}
类程序
{
静态void Main(字符串[]参数)
{
//联系
var dbFactory=new或mliteconnectionfactory(@“Server=。\dev;Database=survey;Trusted_Connection=True;”,sqlserverdial.Provider);
//开放连接
IDbConnection db=dbFactory.OpenDbConnection();
db.DropAndCreateTable();
//创建项目
var newMarket=newMarket(){Id=1,Name=“Shop”,LongName=“Big Shop”};
//将项目添加到数据库
db.InsertParam(新市场);
//用标准方法检索
控制台写入线(“标准方式”);
ShowResult(db.Select(x=>x.Name==“Shop”);
//使用带有将谓词传递到存储库方法的泛型存储库进行检索
WriteLine(“具有传递谓词的通用存储库”);
var genericRepository=新的genericRepository(dbFactory);
ShowResult(genericRepository.FindBy(x=>x.Name==“Shop”);
//使用将specyfic值传递给存储库方法的泛型存储库进行检索
WriteLine(“将specyfic值传递给存储库方法的通用存储库”);
var GenericRepository With HardcodedStatements=新的GenericRepository With HardcodedStatements(dbFactory);
显示结果(带有硬编码数据表的通用存储。查找(“商店”);
WriteLine(“将T对象传递给存储库方法的通用存储库”);
var genericRepositoryWithPassingT=新的genericRepositoryWithPassingT(dbFactory);
ShowResult(GenericRepository with passingt.Find(新市场)()
{
Name=“店铺”
}));
}
私有静态无效显示结果(IEnumerable markets)
{
foreach(市场中的var市场)
{
WriteLine(值:string.Format(“{0}-{1}-{2}”,market.Id,market.Name,market.LongName));
}
}
}
公共类GenericRepository,其中T:class,new()
{
私有只读IDbConnectionFactory dbConnectionFactory;
公共通用存储库(IDbConnectionFactory dbConnectionFactory)
{
this.dbConnectionFactory=dbConnectionFactory;
}
公共IEnumerable FindBy(表达式谓词)
{
返回dbConnectionFactory.OpenDbConnection().SelectParam(谓词);
}
}
带有硬编码数据的公共类GenericRepository,其中T:IReferenceItem,new()
{
私有只读IDbConnectionFactory dbConnectionFactory;
具有硬编码数据的公共一般存储(IDbConnectionFactory dbConnectionFactory)
{
this.dbConnectionFactory=dbConnectionFactory;
}
公共IEnumerable查找(字符串名称)
{
返回dbConnectionFactory.OpenDbConnection().SelectParam(x=>x.Name==Name);
}
}
公共类GenericRepository with passingt,其中T:IReferenceItem,new()
{
私有只读IDbConnectionFactory dbConnectionFactory;
具有passingt的公共一般存储(IDbConnectionFactory dbConnectionFactory)
{
this.dbConnectionFactory=dbConnectionFactory;
}
公共IEnumerable查找(T项)
{
返回dbConnectionFactory.OpenDbConnection().SelectParam(x=>x.Name==item.Name);
}
}
public class GenericRepository<T> : IRepository<T>
where T : class, new()
{
private readonly IDbConnectionFactory dbConnectionFactory;
public GenericRepository(IDbConnectionFactory dbConnectionFactory)
{
this.dbConnectionFactory = dbConnectionFactory;
}
public IEnumerable<T> FindAll()
{
return dbConnectionFactory.OpenDbConnection().Select<T>();
}
public IEnumerable<T> FindBy(Expression<Func<T, bool>> predicate)
{
return dbConnectionFactory.OpenDbConnection().SelectParam<T>(predicate);
}
public T FindById(int id)
{
return dbConnectionFactory.OpenDbConnection().GetById<T>(id);
}
public void Update(T entity)
{
dbConnectionFactory.OpenDbConnection().UpdateParam(entity);
}
public void Remove(T entity)
{
dbConnectionFactory.OpenDbConnection().Delete(entity);
}
public T FirstOrDefault(Expression<Func<T, bool>> predicate)
{
return dbConnectionFactory.OpenDbConnection().FirstOrDefault(predicate);
}
public void Insert(T entity)
{
dbConnectionFactory.OpenDbConnection().InsertParam(entity);
}
class Program
{
static void Main(string[] args)
{
//connection
var dbFactory = new OrmLiteConnectionFactory(@"Server=.\dev;Database=survey;Trusted_Connection=True;", SqlServerDialect.Provider);
//open connection
IDbConnection db = dbFactory.OpenDbConnection();
db.DropAndCreateTable<Market>();
//create item
var newMarket = new Market() { Id = 1, Name = "Shop", LongName = "Big Shop" };
//add item to database
db.InsertParam<Market>(newMarket);
//retrive using standard way
Console.WriteLine("Standard way");
ShowResult(db.Select<Market>(x => x.Name == "Shop"));
//retrive using generic repository with passing predicate to repository method
Console.WriteLine("Generic repository with passing predicate");
var genericRepository = new GenericRepository<Market>(dbFactory);
ShowResult(genericRepository.FindBy(x => x.Name == "Shop"));
//retrive using generic repository with passing specyfic value to repository method
Console.WriteLine("Generic repository with passing specyfic value to repository method");
var genericRepositoryWithHardcodedStatments = new GenericRepositoryWithHardcodedStatments<Market>(dbFactory);
ShowResult(genericRepositoryWithHardcodedStatments.Find("Shop"));
Console.WriteLine("Generic repository with passing T object to repository method");
var genericRepositoryWithPassingT = new GenericRepositoryWithPassingT<Market>(dbFactory);
ShowResult(genericRepositoryWithPassingT.Find(new Market()
{
Name = "shop"
}));
}
private static void ShowResult(IEnumerable<Market> markets)
{
foreach (var market in markets)
{
Console.WriteLine(value: string.Format("{0} - {1} - {2}", market.Id, market.Name, market.LongName));
}
}
}
public class GenericRepository<T> where T : class, new()
{
private readonly IDbConnectionFactory dbConnectionFactory;
public GenericRepository(IDbConnectionFactory dbConnectionFactory)
{
this.dbConnectionFactory = dbConnectionFactory;
}
public IEnumerable<T> FindBy(Expression<Func<T, bool>> predicate)
{
return dbConnectionFactory.OpenDbConnection().SelectParam<T>(predicate);
}
}
public class GenericRepositoryWithHardcodedStatments<T> where T : IReferenceItem, new()
{
private readonly IDbConnectionFactory dbConnectionFactory;
public GenericRepositoryWithHardcodedStatments(IDbConnectionFactory dbConnectionFactory)
{
this.dbConnectionFactory = dbConnectionFactory;
}
public IEnumerable<T> Find(string name)
{
return dbConnectionFactory.OpenDbConnection().SelectParam<T>(x => x.Name == name);
}
}
public class GenericRepositoryWithPassingT<T> where T : IReferenceItem, new()
{
private readonly IDbConnectionFactory dbConnectionFactory;
public GenericRepositoryWithPassingT(IDbConnectionFactory dbConnectionFactory)
{
this.dbConnectionFactory = dbConnectionFactory;
}
public IEnumerable<T> Find(T item)
{
return dbConnectionFactory.OpenDbConnection().SelectParam<T>(x => x.Name == item.Name);
}
}
public interface IReferenceItem
{
int Id { get; set; }
string Name { get; set; }
}
public class Market : IReferenceItem
{
public int Id { get; set; }
public string Name { get; set; }
public string LongName { get; set; }
}