1

I have a table FicheArticle with a XML column ART_Fiche.

I created a stored procedure to let me search in that XML column:

DECLARE @statement nvarchar(max) = N'SELECT ART_UniqueID FROM FicheArticle 
    CROSS APPLY ART_Fiche.nodes('''+@XPath+''') as TT(c)'

execute sp_executesql @statement

When I execute this on SQL Server I get 2 responses. First the list I want and the second a "return Value" (I suppose it's to say execute is good or not)

I call this one from my web application with Linq + Entity Framework like that

Dim a = LesDatas.GetArticleFiltred("//Product/ProductFeature[@CategoryFeature_ID=""6137"" and @Value=""DDR2""]")

I get an integer in return... I want the list, not the integer.

With all I read, I think it's on sp_executesql I don't know how specify the output. All sample are on 1 integer (count(*), MAX ...) but don't find for return rows and I don't arrive to adapt others samples.

Thanks for your help


UPDATE 1

I try too

exec ('SELECT ART_UniqueID FROM SHOP_FicheArticle INNER JOIN SHOP_Article ON SHOP_FicheArticle.ART_IDIcecat = SHOP_Article.ART_IDIcecat CROSS APPLY ART_FicheIcecat.nodes('''+@XPath+''') as TT(c)')

And on vb side go on models explorer -> button Obtain informations of column but always in response : no column in return

Update 2

I try solution here to force Entity to have good return

IF 1 = 2 BEGIN
SELECT
    cast(null as nvarchar(500))  as SHOP_FicheArticle
WHERE
    1 = 2  
END

Now Entity have the good return, but When I execute, it fail : not same type of return... Why I'm not so surprise... I see problem with EF and dynamic request :here I try to force in sql side : SET FMTONLY OFF But same problem

The data reader is incompatible with the specified 'ExtranetModel.GetArticleFiltred_Result'. A member of the type, 'SHOP_FicheArticle', does not have a corresponding column in the data reader with the same name.

Community
  • 1
  • 1
YannickIngenierie
  • 486
  • 1
  • 9
  • 24
  • 1
    Are you using the `CROSS APPLY` only as kind of a filter (like you'd do this with `WHERE`) or are you interested in any value from within your XML? – Shnugo Feb 17 '16 at 15:29
  • I follow this topic [here](http://www.a2zmenu.com/blogs/sql/select-values-from-xml-field-in-sql-server.aspx) I need to make a dynamical search on XML file to send me others field in the table. It's a test. I try to path cross apply and where and cross apply send more quickly infos. Do you have a sample from table valued function (inline) ? – YannickIngenierie Feb 17 '16 at 15:34
  • Hi, I just changed my comment, because I don't think that there is a way to bypass dynamic sql if you want to work with dynamic XPath. This will force you to work with a stored procedure. So the main question is: Is the XPath "fully" dynamic or just the values inside? – Shnugo Feb 17 '16 at 15:36
  • I've principally 2 value to check but I almost need to check several times sames values. It's filter on article. If I've RAM I need check Mhz, size ...Each parameter seems I need check CategoryFeature_ID and value and build dynamically my search – YannickIngenierie Feb 17 '16 at 15:43
  • Your Update1: According to the given error message your datareader does not know about the columns to expect. Are you able to add this column to the EF classes yourself? – Shnugo Feb 18 '16 at 10:15
  • I already try it in Update 2 – YannickIngenierie Feb 18 '16 at 10:26
  • I think you did not get the idea correctly: In the link you refer to the example starts with an impossible call. The whole thing you **want** to get sits below. If this answer is correct, this should do the trick. But - as I told you - this is not my field... This question is not pulling enough attention: it is not new enough, there is an answer and it looks on the first sight to be complex. If you want new experts dropping in, you might close this question and start a new one. Place a link to this question and hope for knowing people :-) – Shnugo Feb 18 '16 at 10:34
  • 1
    Hi, I think I got it: Your "Update 2" should not export `AS SHOP_FicheArticle` but `AS ART_UniqueID`. The dynamic SQL returns with this column name... – Shnugo Feb 18 '16 at 12:18

2 Answers2

0

I don't know if this helps you, but you might pass dedicated values into your XPath. But you cannot pass in the XPath itself.

If you deal with differing XPath expressions you will have to go via dynamic SQL, but if you just want to pass in search values you could go with this:

Set the variable @Test to x or y and you'll get the right row in return.

DECLARE @SomeTable TABLE(ID INT, SomeXML XML);
INSERT INTO @SomeTable VALUES
 (1,'<root><a test="x">x</a></root>')
,(2,'<root><a test="y">y</a></root>');

DECLARE @Test VARCHAR(10)='y';

SELECT st.*
FROM @SomeTable AS st
CROSS APPLY st.SomeXML.nodes('/root/a[@test=sql:variable("@Test")]') AS A(B)

It is absolutely easy to create an inline TVF from this:

CREATE TABLE SomeTable (ID INT, SomeXML XML);
INSERT INTO SomeTable VALUES
 (1,'<root><a test="x">x</a></root>')
,(2,'<root><a test="y">y</a></root>');
GO

CREATE FUNCTION dbo.TestFunction(@Test VARCHAR(10))
RETURNS TABLE
AS
RETURN
SELECT st.*
FROM SomeTable AS st
CROSS APPLY st.SomeXML.nodes('/root/a[@test=sql:variable("@Test")]') AS A(B)
;
GO

SELECT * FROM dbo.TestFunction('y');
GO

DROP FUNCTION dbo.TestFunction;
DROP TABLE SomeTable; 
Shnugo
  • 62,351
  • 7
  • 42
  • 92
  • I'll try with function. But it's sur I need to build completly dynamically my Xpath. The search changes according the type of article (Hard drive, RAM, Processor...) and according the parameters the users choise. It's like on market place. You search specifities of hard Drive. You choise some parameter, but if you serach a car, you search on others parameters. – YannickIngenierie Feb 17 '16 at 16:01
  • 1
    In this case you have two ways: Either use dynamic approach (with SP) which puts the logic in your application (creating the XPath expression) or you use a generic XQuery (with many `*` symbols and `local-name()` calls) to create a generic resultset wich you can analyse. This depends on row count, performance, complexity and - mainly!!! - on the structure. If your XML is always the same in structure (but with differing content) I'd go via TVF, if you have to deal with different structures go with SP. – Shnugo Feb 17 '16 at 16:04
  • @YannickIngenierie, is this question solved? Do you need further help? – Shnugo Feb 17 '16 at 21:49
  • Yes I need Help. I can't always have in Entity my rows. When I check models explorer clic on obtain informations of column That response no column in return I Updte my first post – YannickIngenierie Feb 18 '16 at 09:23
  • @YannickIngenierie, You will never be able to get a preview on the results of a stored procedure or anything connected with `EXEC` and dynamic SQL. This would be kind of magic actually... I don't use EF myself, therefore I asked Google with "c# entity framework fill table from stored procedure". Just try it yourself. There are many responses explaining how to fill a table with the results of a SP. Hope this helps. Btw: Please use your right to vote on and accept answers. This is the fuel SO is running with... – Shnugo Feb 18 '16 at 09:36
0

Like said Shnugo ... Update 2 was the good answer correcting

IF 1 = 2 BEGIN
SELECT
    cast(null as nvarchar(112))  as ART_UniqueID
WHERE
    1 = 2  
END

... I try too with success:

option 2

Create new stored procedure Who call first and with a beautifull declare @tbl... insert into @tbl exec(FirstProc @Param) select ART_UniqueID from @tbl

option 3

In one stored procedure

DECLARE @tblAmount  TABLE(ART_UniqueID NVARCHAR(112))
insert into @tblAmount
exec ('SELECT ART_UniqueID FROM SHOP_FicheArticle INNER JOIN SHOP_Article ON SHOP_FicheArticle.ART_IDIcecat = SHOP_Article.ART_IDIcecat CROSS APPLY ART_FicheIcecat.nodes('''+@XPath+''') as TT(c)')
SELECT * FROM @tblAmount

The problem was it's complete string request then EF can't detect properly the structure.

Option 4

Fot this case where I return only one field

exec ('SELECT ART_UniqueID FROM SHOP_FicheArticle INNER JOIN SHOP_Article ON SHOP_FicheArticle.ART_IDIcecat = SHOP_Article.ART_IDIcecat CROSS APPLY ART_FicheIcecat.nodes('''+@XPath+''') as TT(c)')

And on EF : Force result type like scalar of string.

YannickIngenierie
  • 486
  • 1
  • 9
  • 24
  • Hi Yannick. It is very helpful to publish a solution for others searching the same, thx for that. As it was my answer which brought you on the right trip it would be fair to vote it up. Than - please tick your own answer as accepted to mark this question as closed. – Shnugo Feb 19 '16 at 18:19