我正在尝试搜索表格中的XML字段,EF不支持。
如果不使用纯Ado.net,可以在EF中使用本机SQL支持吗?
答案 0 :(得分:72)
对于.NET Framework版本4及更高版本:如果查询未返回任何结果,请使用ObjectContext.ExecuteStoreCommand()
,如果查询返回结果,请使用ObjectContext.ExecuteStoreQuery
。
对于以前的.NET Framework版本,这里有一个示例说明了要做什么。如果查询返回结果,请根据需要替换ExecuteNonQuery()。
static void ExecuteSql(ObjectContext c, string sql)
{
var entityConnection = (System.Data.EntityClient.EntityConnection)c.Connection;
DbConnection conn = entityConnection.StoreConnection;
ConnectionState initialState = conn.State;
try
{
if (initialState != ConnectionState.Open)
conn.Open(); // open connection if not already open
using (DbCommand cmd = conn.CreateCommand())
{
cmd.CommandText = sql;
cmd.ExecuteNonQuery();
}
}
finally
{
if (initialState != ConnectionState.Open)
conn.Close(); // only close connection if not initially open
}
}
答案 1 :(得分:24)
使用Entity Framework 5.0
,您可以使用ExecuteSqlCommand
执行多行/多命令纯SQL
语句。这样您就不需要提供任何后备对象来存储返回的值,因为该方法返回一个int(执行命令后数据库返回的结果)。
样品:
context.Database.ExecuteSqlCommand(@
"-- Script Date: 10/1/2012 3:34 PM - Generated by ExportSqlCe version 3.5.2.18
SET IDENTITY_INSERT [Students] ON;
INSERT INTO [Students] ([StudentId],[FirstName],[LastName],[BirthDate],[Address],[Neighborhood],[City],[State],[Phone],[MobilePhone],[Email],[Enrollment],[Gender],[Status]) VALUES (12,N'First Name',N'SecondName',{ts '1988-03-02 00:00:00.000'},N'RUA 19 A, 60',N'MORADA DO VALE',N'BARRA DO PIRAÍ',N'Rio de Janeiro',N'3346-7125',NULL,NULL,{ts '2011-06-04 21:25:26.000'},2,1);
INSERT INTO [Students] ([StudentId],[FirstName],[LastName],[BirthDate],[Address],[Neighborhood],[City],[State],[Phone],[MobilePhone],[Email],[Enrollment],[Gender],[Status]) VALUES (13,N'FirstName',N'LastName',{ts '1976-04-12 00:00:00.000'},N'RUA 201, 2231',N'RECANTO FELIZ',N'BARRA DO PIRAÍ',N'Rio de Janeiro',N'3341-6892',NULL,NULL,{ts '2011-06-04 21:38:38.000'},2,1);
");
有关详情,请点击此处:Entity Framework Code First: Executing SQL files on database creation
答案 2 :(得分:17)
对于 实体框架5 ,请使用 context.Database.SqlQuery
。
对于 实体框架4 ,请使用 context.ExecuteStoreQuery
以下代码:
public string BuyerSequenceNumberMax(int buyerId)
{
string sequenceMaxQuery = "SELECT TOP(1) btitosal.BuyerSequenceNumber FROM BuyerTakenItemToSale btitosal " +
"WHERE btitosal.BuyerID = " + buyerId +
"ORDER BY CONVERT(INT,SUBSTRING(btitosal.BuyerSequenceNumber,7, LEN(btitosal.BuyerSequenceNumber))) DESC";
var sequenceQueryResult = context.Database.SqlQuery<string>(sequenceMaxQuery).FirstOrDefault();
string buyerSequenceNumber = string.Empty;
if (sequenceQueryResult != null)
{
buyerSequenceNumber = sequenceQueryResult.ToString();
}
return buyerSequenceNumber;
}
要返回List,请使用以下代码:
public List<PanelSerialList> PanelSerialByLocationAndStock(string locationCode, byte storeLocation, string itemCategory, string itemCapacity, byte agreementType, string packageCode)
{
string panelSerialByLocationAndStockQuery = "SELECT isws.ItemSerialNo, im.ItemModel " +
"FROM Inv_ItemMaster im " +
"INNER JOIN " +
"Inv_ItemStockWithSerialNoByLocation isws " +
" ON im.ItemCode = isws.ItemCode " +
" WHERE isws.LocationCode = '" + locationCode + "' AND " +
" isws.StoreLocation = " + storeLocation + " AND " +
" isws.IsAvailableInStore = 1 AND " +
" im.ItemCapacity = '" + itemCapacity + "' AND " +
" isws.ItemSerialNo NOT IN ( " +
" Select sp.PanelSerialNo From Special_SpecialPackagePriceForResale sp " +
" Where sp.PackageCode = '" + packageCode + "' )";
return context.Database.SqlQuery<PanelSerialList>(panelSerialByLocationAndStockQuery).ToList();
}
答案 3 :(得分:16)
从.NET 4开始,您可以使用ExecuteStoreQuery
方法:
var list = myDBEntities.ExecuteStoreQuery<MyClass>(MyClass.sql);
其中myDBEntities继承自ObjectContext。
class MyClass
{
/* You can change query to more complicated, e.g. with joins */
public const string sql = @"select [MyTable].[MyField] from [MyTable]";
public string MyField { get; set; }
}
请注意,MyTable是真正的表名,而不是EF类。
答案 4 :(得分:3)
保持简单
using (var context = new MyDBEntities())
{
var m = context.ExecuteStoreQuery<MyDataObject>("Select * from Person", string.Empty);
//Do anything you wonna do with
MessageBox.Show(m.Count().ToString());
}
答案 5 :(得分:2)
public class RaptorRepository<T>
where T : class
{
public RaptorRepository()
: this(new RaptorCoreEntities())
{
}
public RaptorRepository(ObjectContext repositoryContext)
{
_repositoryContext = repositoryContext ?? new RaptorCoreEntities();
_objectSet = repositoryContext.CreateObjectSet<T>();
}
private ObjectContext _repositoryContext;
private ObjectSet<T> _objectSet;
public ObjectSet<T> ObjectSet
{
get
{
return _objectSet;
}
}
public void DeleteAll()
{
_repositoryContext
.ExecuteStoreCommand("DELETE " + _objectSet.EntitySet.ElementType.Name);
}
}
答案 6 :(得分:0)
那么2017年我们怎么说呢? 80k的咨询表明,在EF中运行SQL请求是很多人想要做的事情。但为什么?为了什么好处?
Justin,一位拥有20倍声望的大师,在接受的答案中给了我们一个静态的方法,看起来像等效的ADO代码一样。一定要好好复制,因为有一些细微之处,不会出错。而且您不得不将查询与运行时参数连接起来,因为没有提供适当的参数。因此,此方法的所有用户都将使用字符串方法(脆弱,不可测试,sql注入)构建SQL,并且它们都不会进行单元测试。
其他答案有相同的错误,只有更多。 SQL埋在双引号中。 SQL注入机会自由散乱。尊敬的同行,这绝对是野蛮的行为。如果这是生成C#,就会发生火焰战。我们甚至不接受以这种方式生成HTML,但不知何故它可以用于SQL。我知道查询参数不是问题的主题,但我们复制并重用我们看到的内容,这里的答案都是人们正在做的模型和测试。
EF是否融化了我们的大脑? EF不希望您使用SQL,因此为什么要使用EF来执行SQL。想要使用SQL与关系数据库交谈是成年人健康,正常的冲动。 QueryFirst 显示了如何智能地完成此操作,您的sql in .sql文件,在您键入时验证,并使用表和列的intellisense。 C#包装器由该工具生成,因此您的查询在代码中可被发现,并具有用于输入和结果的智能感知。端到端的强力打字,无需担心类型。无需记住列名或其索引。还有许多其他好处......连接的诱惑是删除。也错误处理你的连接的可能性。您的所有查询和访问它们的代码都会针对您的dev DB进行持续集成测试。数据库中的架构更改会在应用程序中弹出为编译错误。我们甚至在包装器中生成自测试方法,因此您可以针对现有的生产数据库测试您的应用程序的新版本,而不是等待手机响铃。还有人需要说服吗?
免责声明:我写过QueryFirst: - )