|
30 | 30 | using System.Linq; |
31 | 31 | using System.Text; |
32 | 32 | using System.ComponentModel.DataAnnotations.Schema; |
| 33 | +using System.Data.Entity.Core.Mapping; |
33 | 34 | using System.Data.Entity.Core.Metadata.Edm; |
34 | 35 | using System.Data.Entity.Core.Objects; |
35 | 36 | using System.Data.Entity.Infrastructure; |
@@ -58,6 +59,7 @@ public abstract class EntityFrameworkTestBase : TestBase |
58 | 59 | createSequenceConn.ExecuteNonQuery("alter table \"dbo\".\"Posts\" alter column \"VarbitColumn\" type varbit using null"); |
59 | 60 | createSequenceConn.ExecuteNonQuery("CREATE OR REPLACE FUNCTION \"dbo\".\"StoredAddFunction\"(integer, integer) RETURNS integer AS $$ SELECT $1 + $2; $$ LANGUAGE SQL;"); |
60 | 61 | createSequenceConn.ExecuteNonQuery("CREATE OR REPLACE FUNCTION \"dbo\".\"StoredEchoFunction\"(integer) RETURNS integer AS $$ SELECT $1; $$ LANGUAGE SQL;"); |
| 62 | + createSequenceConn.ExecuteNonQuery("CREATE OR REPLACE FUNCTION \"dbo\".\"GetBlogsByName\"(text) RETURNS TABLE(\"BlogId\" int, \"Name\" text, \"IntComputedValue\" int) as $$ select \"BlogId\", \"Name\", \"IntComputedValue\" from \"dbo\".\"Blogs\" where \"Name\" ilike '%' || $1 || '%' $$ LANGUAGE SQL;"); |
61 | 63 | } |
62 | 64 | } |
63 | 65 |
|
@@ -144,6 +146,15 @@ public static int StoredEchoFunction(int value) |
144 | 146 | throw new NotSupportedException(); |
145 | 147 | } |
146 | 148 |
|
| 149 | + [DbFunction("BloggingContext", "GetBlogsByName")] |
| 150 | + public IQueryable<Blog> GetBlogsByName(string name) |
| 151 | + { |
| 152 | + ObjectParameter nameParameter = new ObjectParameter("Name", name); |
| 153 | + |
| 154 | + return ((IObjectContextAdapter)this).ObjectContext.CreateQuery<Blog>( |
| 155 | + $"[GetBlogsByName](@Name)", nameParameter); |
| 156 | + } |
| 157 | + |
147 | 158 | private static DbCompiledModel CreateModel(NpgsqlConnection connection) |
148 | 159 | { |
149 | 160 | var dbModelBuilder = new DbModelBuilder(DbModelBuilderVersion.Latest); |
@@ -213,6 +224,87 @@ private static DbCompiledModel CreateModel(NpgsqlConnection connection) |
213 | 224 | null); |
214 | 225 | dbModel.StoreModel.AddItem(echoFunc); |
215 | 226 |
|
| 227 | + var stringStoreType = dbModel.ProviderManifest.GetStoreTypes().First(x => x.ClrEquivalentType == typeof(string)); |
| 228 | + var modelBlogStoreType = dbModel.StoreModel.EntityTypes.First(x => x.Name == typeof(Blog).Name); |
| 229 | + var rowType = RowType.Create( |
| 230 | + modelBlogStoreType.Properties.Select(x => |
| 231 | + { |
| 232 | + var clone = EdmProperty.Create(x.Name, x.TypeUsage); |
| 233 | + clone.CollectionKind = x.CollectionKind; |
| 234 | + clone.ConcurrencyMode = x.ConcurrencyMode; |
| 235 | + clone.IsFixedLength = x.IsFixedLength; |
| 236 | + clone.IsMaxLength = x.IsMaxLength; |
| 237 | + clone.IsUnicode = x.IsUnicode; |
| 238 | + clone.MaxLength = x.MaxLength; |
| 239 | + clone.Precision = x.Precision; |
| 240 | + clone.Scale = x.Scale; |
| 241 | + clone.StoreGeneratedPattern = x.StoreGeneratedPattern; |
| 242 | + clone.SetMetadataProperties(x |
| 243 | + .MetadataProperties |
| 244 | + .Where(metadataProerty => !clone |
| 245 | + .MetadataProperties |
| 246 | + .Any(cloneMetadataProperty => cloneMetadataProperty.Name.Equals(metadataProerty.Name)))); |
| 247 | + return clone; |
| 248 | + }), |
| 249 | + null); |
| 250 | + |
| 251 | + var getBlogsFunc = EdmFunction.Create( |
| 252 | + "StoredGetBlogsFunction", |
| 253 | + "BloggingContext", |
| 254 | + DataSpace.SSpace, |
| 255 | + new EdmFunctionPayload |
| 256 | + { |
| 257 | + ParameterTypeSemantics = ParameterTypeSemantics.AllowImplicitConversion, |
| 258 | + Schema = "dbo", |
| 259 | + IsComposable = true, |
| 260 | + IsNiladic = false, |
| 261 | + IsBuiltIn = false, |
| 262 | + IsAggregate = false, |
| 263 | + StoreFunctionName = "GetBlogsByName", |
| 264 | + ReturnParameters = new[] |
| 265 | + { |
| 266 | + FunctionParameter.Create("ReturnType1", rowType.GetCollectionType(), ParameterMode.ReturnValue) |
| 267 | + }, |
| 268 | + Parameters = new[] |
| 269 | + { |
| 270 | + FunctionParameter.Create("Name", stringStoreType, ParameterMode.In) |
| 271 | + } |
| 272 | + }, |
| 273 | + null); |
| 274 | + dbModel.StoreModel.AddItem(getBlogsFunc); |
| 275 | + |
| 276 | + var stringPrimitiveType = PrimitiveType.GetEdmPrimitiveTypes().First(x => x.ClrEquivalentType == typeof(string)); |
| 277 | + var modelBlogConceptualType = dbModel.ConceptualModel.EntityTypes.First(x => x.Name == typeof(Blog).Name); |
| 278 | + EdmFunction getBlogsFuncModel = EdmFunction.Create( |
| 279 | + "GetBlogsByName", |
| 280 | + dbModel.ConceptualModel.Container.Name, |
| 281 | + DataSpace.CSpace, |
| 282 | + new EdmFunctionPayload |
| 283 | + { |
| 284 | + IsFunctionImport = true, |
| 285 | + IsComposable = true, |
| 286 | + Parameters = new[] |
| 287 | + { |
| 288 | + FunctionParameter.Create("Name", stringPrimitiveType, ParameterMode.In) |
| 289 | + }, |
| 290 | + ReturnParameters = new[] |
| 291 | + { |
| 292 | + FunctionParameter.Create("ReturnType1", modelBlogConceptualType.GetCollectionType(), ParameterMode.ReturnValue) |
| 293 | + }, |
| 294 | + EntitySets = new[] |
| 295 | + { |
| 296 | + dbModel.ConceptualModel.Container.EntitySets.First(x => x.ElementType == modelBlogConceptualType) |
| 297 | + } |
| 298 | + }, |
| 299 | + null); |
| 300 | + dbModel.ConceptualModel.Container.AddFunctionImport(getBlogsFuncModel); |
| 301 | + |
| 302 | + dbModel.ConceptualToStoreMapping.AddFunctionImportMapping(new FunctionImportMappingComposable( |
| 303 | + getBlogsFuncModel, |
| 304 | + getBlogsFunc, |
| 305 | + new FunctionImportResultMapping(), |
| 306 | + dbModel.ConceptualToStoreMapping)); |
| 307 | + |
216 | 308 | var compiledModel = dbModel.Compile(); |
217 | 309 | return compiledModel; |
218 | 310 | } |
|
0 commit comments