Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do we have to write SET FMTONLY OFF in stored procedures when using Entity Framework

I recently joined one of the project in my team. They use ASP.NET MVC and MS SQL along with Entity Framework as ORM.

I noticed that each of the stored procedures used in the EF has this common line at the start of the stored procedure definitation

IF(0=1) SET FMTONLY OFF

I thought this was a very strange condition so I googled a bit about it and also asked my co workers about it. They say that when EF maps the stored procedure it send all parameters as null and skips all the if loop. Hence it would also skip the IF(0=1) condition and would then SET FMTONLY OFF

On searching for SET FMTONLY OFF MSDN, says

Returns only metadata to the client. Can be used to test the format of the response without actually running the query.

It becomes a problem when you dont control the database, you have to keep telling the DBA's to add it and explain to them over and over again why is it needed in the first place.

I still dont have a clear idea why this is required. If someone can explain this a bit in detail or guide me to some link which has this topic covered would mean the world to me.

like image 313
Yasser Shaikh Avatar asked Jul 17 '14 03:07

Yasser Shaikh


People also ask

Why we use set Fmtonly off?

Answers. Entity Framework executes SET FMTONLY ON before every sp call and and it will only return column metadata and no actual data is being retrieved. When you do SET FMTONLY OFF, you are overriding that.

What is Fmtonly off?

When FMTONLY is ON , a rowset is returned with the column names, but without any data rows. SET FMTONLY ON has no effect when the Transact-SQL batch is parsed. The effect occurs during execution run time. The default value is OFF .

Why do stored procedures need to be recompiled?

If a database undergoes significant changes to its data or structure, recompiling a procedure updates and optimizes the procedure's query plan for those changes. This can improve the procedure's processing performance.

Can we use Entity Framework with stored procedure?

The Entity Framework has the capability of importing a Stored Procedure as a function. We can also map the result of the function back to any entity type or complex type.


2 Answers

I believe the reason is similar to the one for stored procedures that run from SSRS. In summary, when FMTONLY is active, your stored procedure may have some unexpected results. Hence the reason for explicitly turning it off. For details read Dealing with the Evil of FMTONLY from SSRS

like image 115
David Avatar answered Oct 29 '22 13:10

David


Having IF(0=1) SET FMTONLY OFF seems like a risky thing to casually do in stored procedures read in by entity framework.

Entity Framework is the only source of this flag being set as a standard practice that I'm aware of (presumably other ORM's may use it).

the purpose (as I understand it) is to provide a way to get a procedures return schema without actually touching any data. (some stored procedures you don't want to execute just to update an orm's object model.

so unless you have a table that is counting the number of times your EF model has been updated (which might be interesting academically)

for additional information see Stored procedure returns int instead of result set

the safest way to use ftmonly with entity framework (in my mind) is.. under the following circumstances

  1. if the procedure in question is complex and confuses EF (EF reads the first returned schema, flow logic ignored)
  2. let EF set the flag for you. (I clear it below to exit early)
  3. use always false logic (which would be ignored when FTMONLY is on - interpret this as EF is trying to read schema)
  4. at the beginning of the complex procedure do the following

    if(0=1)  -- if FMTONLY is on this if condition is ignored
    begin
        -- this loop will only be entered if fmtonly is on (ie EF schema read)
        select 
            column1
            ,column2
            ...
            ,columnX
        from whateverA
            cross join whateverB
            ...
            cross join whateverQ
        -- joins don't matter but they might make it easier to get the column definitions
        -- and names you desire.   the important thing here is generating the proper 
        -- return schema... which is as complex as whatever you are trying to return
        where 1=0
    
        set FMTONLY off -- do this so that you can now force an early return since EF
        -- usually only wants the first data set schema...  other orms might
        -- do something different
        return  -- this will be ignored if FMTONLY is still on
    
    end
    
like image 27
wode Avatar answered Oct 29 '22 14:10

wode