2009-05-27 8 views
64

J'essaie de rechercher un champ XML dans une table, Ceci n'est pas supporté par EF.Est-il possible d'exécuter sql natif avec framework d'entité?

Sans utiliser pur Ado.net est possible d'avoir un support SQL natif avec EF?

+0

Veuillez clarifier votre question. Lorsque vous posez des questions sur le "support SQL natif", voulez-vous dire plus que "support des colonnes XML"? De quoi d'autre parlez-vous? De plus, quel problème avez-vous eu avec la colonne XML? N'a-t-il tout simplement pas pénétré dans l'entité, ou y a-t-il eu un problème lorsque vous avez essayé de l'utiliser? Aussi, dites-nous quelle version vous utilisiez? 2008, 2008 SP1, 2010 CTP ou Beta 1? –

Répondre

71

Pour .NET Framework version 4 et ultérieure: utilisez ObjectContext.ExecuteStoreCommand() si votre requête ne renvoie aucun résultat et utilisez ObjectContext.ExecuteStoreQuery si votre requête renvoie des résultats.

Pour les versions précédentes de .NET Framework, voici un exemple illustrant ce qu'il faut faire. Remplacez ExecuteNonQuery() si nécessaire si votre requête renvoie des résultats.

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 
    } 
} 
+38

Cette réponse est périmée. Voir cet article http://geekswithblogs.net/rgupta/archive/2010/06/23/entity-framework-v4-ndash-tips-and-tricks.aspx. Vous pouvez exécuter Sql directement à partir d'un framework d'entité sans wrapper requis en utilisant ** ExecuteStoreCommand ** ou ** ExecuteStoreQuery ** dès la sortie de l'instance Entity. –

+9

Gardez à l'esprit que ces méthodes ne sont pas supportées par DbContext, mais il existe Database.ExecuteSqlCommand() ou Database.SqlQuery . – nicodemus13

+1

@ user297691 - J'ai mis à jour la réponse avec de nouvelles infos. Merci! –

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); 
    } 
} 
16

Depuis .NET 4, vous pouvez utiliser la méthode ExecuteStoreQuery:

var list = myDBEntities.ExecuteStoreQuery<MyClass>(MyClass.sql); 

où myDBEntities est héritée de 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; } 
} 

Notez que MyTable est le vrai nom de la table, pas la classe EF.

+1

De commentaire ci-dessous, context.Database.SqlQuery fonctionne dans EF5 – Sameer

23

En utilisant Entity Framework 5.0, vous pouvez utiliser ExecuteSqlCommand pour exécuter des instructions SQL pur multi-ligne/multi-commande. De cette façon, vous n'aurez pas besoin de fournir un objet de sauvegarde pour stocker la valeur retournée car la méthode renvoie un int (le résultat renvoyé par la base de données après l'exécution de la commande).

Exemple:

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); 
"); 

Pour en savoir plus, jetez un coup d'oeil ici: Entity Framework Code First: Executing SQL files on database creation

17

Pour Entity Framework 5 d'utilisation context.Database.SqlQuery.

Et pour Entity Framework 4 utilisation context.ExecuteStoreQuery le code suivant:

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; 
    } 

Pour retourner une liste utilisez le code suivant:

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

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()); 
} 
0

Alors qu'est-ce qu'on dit de tout ça en 2017? 80k consultations suggère que l'exécution d'une requête SQL dans EF est quelque chose que beaucoup de gens veulent faire. Mais pourquoi? Pour quel bénéfice? Justin, un gourou avec 20 fois ma réputation, dans la réponse acceptée nous donne une méthode statique qui ressemble ligne à ligne comme le code ADO équivalent. Assurez-vous de bien le copier car il y a quelques subtilités pour ne pas se tromper. Et vous êtes obligé de concaténer votre requête avec vos paramètres d'exécution car il n'y a aucune disposition pour les paramètres appropriés.Tous les utilisateurs de cette méthode construiront donc leur SQL avec des méthodes de type chaîne (fragile, non testable, injection SQL), et aucun d'entre eux ne sera un test unitaire.

Les autres réponses ont les mêmes défauts, mais plus encore. SQL enterré entre guillemets. Opportunités d'injection SQL généreusement dispersées. Des pairs estimés, c'est un comportement absolument sauvage. Si c'était C# généré, il y aurait une guerre de flamme. Nous n'acceptons même pas la génération de HTML de cette façon, mais c'est OK pour SQL. Je sais que les paramètres de la requête n'étaient pas le sujet de la question, mais nous copions et réutilisons ce que nous voyons, et les réponses ici sont à la fois des modèles et des testaments de ce que font les gens.

Est-ce que EF a fait fondre notre cerveau? EF ne veut pas que vous utilisiez SQL, alors pourquoi utiliser EF pour faire du SQL.

Vouloir utiliser SQL pour parler à une base de données relationnelle est une impulsion saine et normale chez les adultes. QueryFirst montre comment cela pourrait être fait intelligemment, votre fichier sql in .sql, validé lors de la frappe, avec intellisense pour les tables et les colonnes. L'encapsuleur C# est généré par l'outil, de sorte que vos requêtes deviennent détectables dans le code, avec intellisense pour vos entrées et résultats. Fin à la frappe forte, sans jamais avoir à se soucier d'un type. Pas besoin de se souvenir d'un nom de colonne ou de son index. Et il existe de nombreux autres avantages ... La tentation de concaténer est retiré. La possibilité de mal gérer vos connexions aussi. Toutes vos requêtes et le code qui y accède sont continuellement testés sur votre base de données de développement. Les changements de schéma dans votre base de données apparaissent comme des erreurs de compilation dans votre application. Nous générons même une méthode de test automatique dans le wrapper, de sorte que vous pouvez tester les nouvelles versions de votre application par rapport aux bases de données de production existantes, plutôt que d'attendre que le téléphone sonne. Quelqu'un a encore besoin de convaincre?

Clause de non-responsabilité: J'ai écrit QueryFirst :-)

Questions connexes