Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>You can accomplish this in EF 6 code-first by mapping a C# function to a database function. It took some tweaking and doesn't produce the most efficient SQL, but it gets the job done.</p> <p>First, create a function in the database to test for a newer rowversion. Mine is</p> <pre><code>CREATE FUNCTION [common].[IsNewerThan] ( @CurrVersion varbinary(8), @BaseVersion varbinary(8) ) ... </code></pre> <p>When constructing your EF context, you'll have to manually define the function in the store model, like this:</p> <pre><code>private static DbCompiledModel GetModel() { var builder = new DbModelBuilder(); ... // your context configuration var model = builder.Build(...); EdmModel store = model.GetStoreModel(); store.AddItem(GetRowVersionFunctionDef(model)); DbCompiledModel compiled = model.Compile(); return compiled; } private static EdmFunction GetRowVersionFunctionDef(DbModel model) { EdmFunctionPayload payload = new EdmFunctionPayload(); payload.IsComposable = true; payload.Schema = "common"; payload.StoreFunctionName = "IsNewerThan"; payload.ReturnParameters = new FunctionParameter[] { FunctionParameter.Create("ReturnValue", GetStorePrimitiveType(model, PrimitiveTypeKind.Boolean), ParameterMode.ReturnValue) }; payload.Parameters = new FunctionParameter[] { FunctionParameter.Create("CurrVersion", GetRowVersionType(model), ParameterMode.In), FunctionParameter.Create("BaseVersion", GetRowVersionType(model), ParameterMode.In) }; EdmFunction function = EdmFunction.Create("IsRowVersionNewer", "EFModel", DataSpace.SSpace, payload, null); return function; } private static EdmType GetStorePrimitiveType(DbModel model, PrimitiveTypeKind typeKind) { return model.ProviderManifest.GetStoreType(TypeUsage.CreateDefaultTypeUsage( PrimitiveType.GetEdmPrimitiveType(typeKind))).EdmType; } private static EdmType GetRowVersionType(DbModel model) { // get 8-byte array type var byteType = PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Binary); var usage = TypeUsage.CreateBinaryTypeUsage(byteType, true, 8); // get the db store type return model.ProviderManifest.GetStoreType(usage).EdmType; } </code></pre> <p>Create a proxy for the method by decorating a static method with the DbFunction attribute. EF uses this to associate the method with the named method in the store model. Making it an extension method produces cleaner LINQ.</p> <pre><code>[DbFunction("EFModel", "IsRowVersionNewer")] public static bool IsNewerThan(this byte[] baseVersion, byte[] compareVersion) { throw new NotImplementedException("You can only call this method as part of a LINQ expression"); } </code></pre> <h1>Example</h1> <p>Finally, call the method from LINQ to entities in a standard expression.</p> <pre><code> using (var db = new OrganizationContext(session)) { byte[] maxRowVersion = db.Users.Max(u =&gt; u.RowVersion); var newer = db.Users.Where(u =&gt; u.RowVersion.IsNewerThan(maxRowVersion)).ToList(); } </code></pre> <p>This generates the T-SQL to achieve what you want, using the context and entity sets you have defined.</p> <pre><code>WHERE ([common].[IsNewerThan]([Extent1].[RowVersion], @p__linq__0)) = 1',N'@p__linq__0 varbinary(8000)',@p__linq__0=0x000000000001DB7B </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload