简体   繁体   中英

How to properly use InOut ObjectParameter in EF4?

I recently had cause to bring back just a single value in addition to tabular data returned by my stored procedure. Since EF doesn't support stored procedures with multiple result sets, I figured I could accomplish this via an output parameter. However, using this method I encountered an issue where in I was getting only rounded values back for some numeric value fields.

The parameter to my stored procedure was declared as:

@MyValue    numeric(19,6) output

When calling the mapping function, I had:

var myValue = new ObjectParameter("MyValue", typeof(decimal));
List<MyResultItem> results = this.ObjectContext.CallMyStoredProc(someId, myValue).ToList();

This is what always returned the value rounded to an integer (ie, scale zero).

I was first able to fix this by manually editing the underlying XML to the .edmx by manually adding Precision and Scale attributes:

<Parameter Name="MyValue" Type="numeric" Mode="InOut" Precision="19" Scale="6" />

This was, not surprisingly, completely discarded the next time I performed "Update Model from Database.."

I seem to have fixed it more reliably by updating my declaration for the ObjectParameter as such:

var myValue = new ObjectParameter("MyValue", 999999999.999999M);

However, this seems an awful lot like a hack, and I'm worried about issues in the future (even if it's just maintenance regarding this magic number). Is there a better, and reliable, way to use output parameters within Entity Framework?

I ended up needing this in more places, now, so I created a helper method for it:

/// <summary>
/// Get the maximum allowed value for a SQL numeric of the specified scale and precision.
/// </summary>
/// <param name="scale">The scale.</param>
/// <param name="precision">The precision.</param>
/// <returns>Decimal representing the maximum value for the specified numeric.</returns>
public static decimal SqlNumericMax(int scale, int precision)
{
    return (decimal)Math.Pow(10, (scale - precision)) - (decimal)Math.Pow(10, (-1 * precision));
}

This doesn't absolve the use of magic numbers in code, but at least it does help provide an exact match between what you see in code to what you see in the database. (ie, for a numeric(19,6) stored proc parameter, you'll call Utility.SqlNumericMax(19, 6) , so the relationship is more immediately apparent.)

It looks like providing the maximum value to the parameter prior to the stored proc call is still the best and most reliable method for the call to populate the result correctly.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM