Entity Framework 6をシステムに統合したいのですが、問題があります。
問題は:
[Table]、[Column]などの属性を使用して関数をマップできません。 1つの属性のみが使用可能です[DbFunction]。これには* .edmxファイルが必要です。
* .edmxファイルに関数マッピングを作成してもかまいませんが、エンティティの属性マッピングを使用できないことを意味します:[テーブル]、[列]。マッピングは、*。edmxまたは属性でいっぱいにする必要があります。
私はDbModelを作成し、このコードを介して機能を追加しようとしました:
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;
}
}
ただし、例外があります。
モデル生成中に1つ以上の検証エラーが検出されました。
Edm.String: : The namespace 'String' is a system namespace and cannot be used by other schemas. Choose another namespace name.
問題は「edmType」変数にあります。関数のReturnTypeを正しく作成できません。誰かがモデルに機能を追加する方法を提案できますか?関数を追加するインターフェイスが公開されているため、実行できるはずですが、この状況に関する情報はWebにありません。おそらく、Entity FrameworkチームがLine To Sqlのように関数の属性マッピングをいつ実装するかを知っている人がいるかもしれません。
EFバージョン:6.0.0-beta1-20521
ありがとう!
はい、これは私のために動作します。ただし、スカラー関数のみ。また、IQueryableを返すマップ関数が必要です。
IQueryable<T> MyFunction()
TはEntityTypeまたはRowTypeまたは任意のタイプです。これはまったくできません(EFバージョンは6.0.2-21211です)。これは次のように動作するはずです:
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()));
}
しかし、まだ運がありません:
model.Compile(); // ERROR
可能ですか?おそらく手順は正しくありませんか?おそらくEF 6.1でサポートが追加されるでしょう。どんな情報も非常に役立ちます。
ありがとう!
まだ試していませんが、Entity Framework 6.1には public mapping API が含まれています。 Moozzykは、この新しい機能を使用して EntityFramework CodeFirstのストア関数 を実装しました。
コードは次のようになります。
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);
}
}
必要なすべての手順は次のとおりです[テスト済み]:
Install-Package EntityFramework.CodeFirstStoreFunctions
出力結果のクラスを宣言します。
public class MyCustomObject
{
[Key]
public int Id { get; set; }
public int Rank { get; set; }
}
DbContextクラスにメソッドを作成します
[DbFunction("MyContextType", "SearchSomething")]
public virtual IQueryable<MyCustomObject> SearchSomething(string keywords)
{
var keywordsParam = new ObjectParameter("keywords", typeof(string))
{
Value = keywords
};
return (this as IObjectContextAdapter).ObjectContext
.CreateQuery<MyCustomObject>(
"MyContextType.SearchSomething(@keywords)", keywordsParam);
}
追加
public DbSet<MyCustomObject> SearchResults { get; set; }
dbContextクラスへ
オーバーライドされたOnModelCreating
メソッドを追加します。
modelBuilder.Conventions
.Add(new CodeFirstStoreFunctions.FunctionsConvention<MyContextType>("dbo"));
そして今、あなたは次のようなテーブル値関数で呼び出し/参加することができます:
CREATE FUNCTION SearchSomething
(
@keywords nvarchar(4000)
)
RETURNS TABLE
AS
RETURN
(SELECT KEY_TBL.RANK AS Rank, Id
FROM MyTable
LEFT JOIN freetexttable(MyTable , ([MyColumn1],[MyColumn2]), @keywords) AS KEY_TBL
ON MyTable.Id = KEY_TBL.[KEY]
WHERE KEY_TBL.RANK > 0
)
GO
ヘルパーメソッドを使用して、プリミティブ型からStore型を取得できます。
public static EdmType GetStorePrimitiveType(DbModel model, PrimitiveTypeKind typeKind)
{
return model.ProviderManifest.GetStoreType(TypeUsage.CreateDefaultTypeUsage(
PrimitiveType.GetEdmPrimitiveType(typeKind))).EdmType;
}
この例では、戻りパラメーターのタイプを変更する必要があります。
var edmType = GetStorePrimitiveType(model, PrimitiveTypeKind.String);
ここで必要なヘルプを見つけました: http://entityframework.codeplex.com/discussions/466706
entity Frameworkはベータ版ではないので、おそらくあなたはあなたの問題を解決したかもしれませんが、これは私の問題を解決しました linq to entityでスカラー値関数を使用する方法?