Is it possible to run native sql with entity framework?
I am trying to search an XML field within a table, This is not supported with EF.
Without using pure Ado.net is possible to have native SQL support with EF?
For .NET Framework version 4 and above: use ObjectContext.ExecuteStoreCommand()
if your query returns no results, and use ObjectContext.ExecuteStoreQuery
if your query returns results.
For previous .NET Framework versions, here's a sample illustrating what to do. Replace ExecuteNonQuery() as needed if your query returns results.
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
}
}
Using Entity Framework 5.0
you can use ExecuteSqlCommand
to execute multi-line/multi-command pure SQL
statements. This way you won't need to provide any backing object to store the returned value since the method returns an int (the result returned by the database after executing the command).
Sample:
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);
");
For more on this, take a look here: Entity Framework Code First: Executing SQL files on database creation
For Entity Framework 5 use context.Database.SqlQuery
.
And for Entity Framework 4 use context.ExecuteStoreQuery
the following code:
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;
}
To return a List use the following code:
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();
}
Since .NET 4 you can use ExecuteStoreQuery
method:
var list = myDBEntities.ExecuteStoreQuery<MyClass>(MyClass.sql);
where myDBEntities is inherited from 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; }
}
Notice that MyTable is real table name, not EF class.
Keep it simple
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());
}