Voglio integrare Entity Framework 6 nel nostro sistema, ma ho dei problemi.
Il problema è:
Non riesco a mappare la funzione tramite attributi come [Tabella], [Colonna]. È disponibile solo 1 attributo [DbFunction], che richiede il file * .edmx.
Sto bene per avere il mapping delle funzioni nel file * .edmx, ma significa che non posso usare la mappatura degli attributi per le Entità: [Tabella], [Colonna]. La mappatura deve essere piena in * .edmx o negli attributi.
Ho provato a creare DbModel e aggiungere funzioni tramite questo codice:
public static class Functions
{
[DbFunction("CodeFirstNamespace", "TestEntity")]
public static string TestEntity()
{
throw new NotSupportedException();
}
}
public class MyContext : DbContext, IDataAccess
{
protected MyContext (string connectionString)
: base(connectionString, CreateModel())
{
}
private static DbCompiledModel CreateModel()
{
var dbModelBuilder = new DbModelBuilder(DbModelBuilderVersion.Latest);
dbModelBuilder.Entity<Warehouse>();
var dbModel = dbModelBuilder.Build(new DbProviderInfo("System.Data.SqlClient", "2008"));
var edmType = PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.String);
var payload =
new EdmFunctionPayload
{
Schema = "dbo",
ParameterTypeSemantics = ParameterTypeSemantics.AllowImplicitConversion,
IsComposable = true,
IsNiladic = false,
IsBuiltIn = false,
IsAggregate = false,
IsFromProviderManifest = true,
StoreFunctionName = "TestEntity",
ReturnParameters =
new[]
{
FunctionParameter.Create("ReturnType", edmType, ParameterMode.ReturnValue)
}
};
var function = EdmFunction.Create("TestEntity", "CodeFirst", DataSpace.CSpace, payload, null);
dbModel.DatabaseMapping.Model.AddItem(function);
var compiledModel = dbModel.Compile(); // Error happens here
return compiledModel;
}
}
Ma hanno un'eccezione:
Uno o più errori di convalida sono stati rilevati durante la generazione del modello:
Edm.String: : The namespace 'String' is a system namespace and cannot be used by other schemas. Choose another namespace name.
Il problema è nella variabile "edmType ". Non riesco a creare correttamente ReturnType per la funzione. Qualcuno può suggerire come posso aggiungere la funzione nel modello? L'interfaccia della funzione di aggiunta è esposta, quindi dovrebbe essere in grado di fare, ma non ci sono informazioni nel web per questa situazione. Probabilmente, qualcuno sa quando il team di Entity Framework implementerà la mappatura degli attributi per funzioni come Line To Sql.
Versione EF: 6.0.0-beta1-20521
Grazie!
Sì, questo funziona per me. Ma solo per le funzioni scalari. Anch'io ho bisogno della funzione map, che restituisce IQueryable:
IQueryable<T> MyFunction()
Dove T è EntityType o RowType o qualsiasi tipo. Non riesco a farlo affatto (la versione EF è 6.0.2-21211). Penso che questo dovrebbe funzionare in questo modo:
private static void RegisterEdmFunctions(DbModel model)
{
var storeModel = model.GetStoreModel();
var functionReturnValueType = storeModel.EntityTypes.Single(arg => arg.Name == "MyEntity").GetCollectionType();
var payload =
new EdmFunctionPayload
{
IsComposable = true,
Schema = "dbo",
StoreFunctionName = "MyFunctionName",
ReturnParameters =
new[]
{
FunctionParameter.Create("ReturnValue", functionReturnValueType, ParameterMode.ReturnValue)
},
Parameters =
new[]
{
FunctionParameter.Create("MyFunctionInputParameter", PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32), ParameterMode.In)
}
};
storeModel.AddItem(EdmFunction.Create(
payload.StoreFunctionName,
"MyFunctionsNamespace",
DataSpace.SSpace,
payload,
payload.Parameters.Select(arg => MetadataProperty.Create(arg.Name, arg.TypeUsage, null)).ToArray()));
}
Ma ancora senza fortuna:
model.Compile(); // ERROR
E 'possibile o no? Probabilmente i passi non sono giusti? Probabilmente il supporto verrà aggiunto a EF 6.1. Qualsiasi informazione sarà molto utile.
Grazie!
Non ho ancora provato questo, ma Entity Framework 6.1 include API di mapping pubblico . Moozzyk ha implementato le funzioni di archivio per EntityFramework CodeFirst utilizzando questa nuova funzionalità.
Ecco come appare il codice:
public class MyContext : DbContext
{
public DbSet<Customer> Customers { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Add(new FunctionsConvention<MyContext>("dbo"));
}
[DbFunction("MyContext", "CustomersByZipCode")]
public IQueryable<Customer> CustomersByZipCode(string zipCode)
{
var zipCodeParameter = zipCode != null ?
new ObjectParameter("ZipCode", zipCode) :
new ObjectParameter("ZipCode", typeof(string));
return ((IObjectContextAdapter)this).ObjectContext
.CreateQuery<Customer>(
string.Format("[{0}].{1}", GetType().Name,
"[CustomersByZipCode](@ZipCode)"), zipCodeParameter);
}
public ObjectResult<Customer> GetCustomersByName(string name)
{
var nameParameter = name != null ?
new ObjectParameter("Name", name) :
new ObjectParameter("Name", typeof(string));
return ((IObjectContextAdapter)this).ObjectContext.
ExecuteFunction("GetCustomersByName", nameParameter);
}
}