1

これは、EF エンティティ用に汎用の Save() サービスを WCF に実装する方法です。TT が代わりに作業を行います。問題はありませんが、これが最善のアプローチであるとは思いたくありません (たとえそうであったとしても)。皆さんは非常に明るく親切に見えるので、私は質問を投げかけようと思いました:

より良い方法はありますか?

[OperationContract]
public User SaveUser(User entity)
{
    bool _IsDeleted = false;
    using (DatabaseEntities _Context = new DatabaseEntities())
    {
        switch (entity.ChangeTracker.State)
        {
            case ObjectState.Deleted:
                //delete
                _IsDeleted = true;
                _Context.Users.Attach(entity);
                _Context.DeleteObject(entity);
                break;
            default:
                //everything else
                _Context.Users.ApplyChanges(entity);
                break;
        }
        // now, to the database
        try
        {
            // try to save changes, which may cause a conflict.
            _Context.SaveChanges(System.Data.Objects.SaveOptions.None);
        }
        catch (System.Data.OptimisticConcurrencyException)
        {
            // resolve the concurrency conflict by refreshing 
            _Context.Refresh(System.Data.Objects.RefreshMode.ClientWins, entity);
            // Save changes.
            _Context.SaveChanges();
        }
    }
    // return
    if (_IsDeleted)
        return null;
    entity.AcceptChanges();
    return entity;
}
4

2 に答える 2

6

自己追跡エンティティでこれを行うのはなぜですか? これの何が問題でしたか:

[OperationContract]
public User SaveUser(User entity)
{
    bool isDeleted = false;
    using (DatabaseEntities context = new DatabaseEntities())
    {
        isDeleted = entity.ChangeTracker.State == ObjectState.Deleted;
        context.Users.ApplyChanges(entity); // It deletes entities marked for deletion as well

        try
        {
            // no need to postpone accepting changes, they will not be accepted if exception happens
            context.SaveChanges(); 
        }
        catch (System.Data.OptimisticConcurrencyException)
        {
            context.Refresh(System.Data.Objects.RefreshMode.ClientWins, entity);
            context.SaveChanges();
        }
    }

    return isDeleted ? null : entity;
}
于 2011-06-24T08:03:03.627 に答える
2

私が間違っていなければ、人々は通常、EntityFrameworkオブジェクトをWCFサービスで直接公開しません。Entity Frameworkは通常、データアクセス層と見なされ、WCFはフロントエンド層であるため、異なる層に配置されます。

データ転送オブジェクト(DTO)は、WCFメソッドで使用されます。これは通常、状態追跡がまったくないPOCOです。次に、DTOは、手動またはAutoMapperなどのフレームワークを介してエンティティにマップされます。

通常、クライアントはオブジェクトを「追加」するのか「更新する」のかを知っている必要があります。個人的には、これらをサービスインターフェイスでの2つの別個の操作にすることをお勧めします。また、オブジェクトを削除するために別のメソッドを使用することを彼らに絶対に要求します。ただし、一般的な「保存」がどうしても必要な場合は、主キー値の有無に基づいて、指定されたオブジェクトが「新規」であるかどうかを判断できるはずです。

多くのコードを汎用ユーティリティに入れることができます。たとえば、T4テンプレートがエンティティのキ​​ー値に属性を生成すると仮定すると、キー値が存在するかどうかを自動的に判断し、それに応じて挿入/更新を実行できます。また、try SaveChanges catch retry使用しているブロックは、おそらく不要ですが、簡単なユーティリティメソッドに簡単に入れて、よりDRYにすることができます。

于 2011-06-23T23:34:04.513 に答える