Web apiを使用してasp.netのデータベース1列を一度に更新すると、この問題が発生します。 PUTを照会して、行の1つの値を更新し、残りをnullに設定するのではなく、その1つの値を更新しようとしています。コントローラーの外部で個別のモデルを作成して、更新を取り込むため、一度に1つずつ実行できます。エラーが発生しているコントローラーでこの行db.Entry(user).State = EntityState.Modified;
をヒットすると。これを修正する方法はありますか?
これは、putメソッドで使用する別のViewModelです。
namespace WebAPI.Models.ViewModels
{
public class UserViewModel
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
}
これは、パラメーターにViewModelを指定してメソッドを呼び出すコントローラーです。
public HttpResponseMessage PutUser(int id, UserViewModel user)
{
HttpResponseMessage response;
if (db.User.IsInRole("Admin"))
{
try
{
db.Entry(user).State = EntityState.Modified;
db.SaveChanges();
}
catch (DbUpdateConcurrencyException)
{
if (!UserExists(id))
{
response = new HttpResponseMessage(HttpStatusCode.NotFound);
return response;
}
else
{
throw;
}
}
response = new HttpResponseMessage(HttpStatusCode.NoContent);
return response;
}
これは私のDBContext
ファイルです:
public partial class Entities : DbContext
{
public Entities()
: base("name=Entities")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public virtual DbSet<User> Users { get; set; }
}
}
エラーは、データコンテキストdb
を初期化する方法に起因します。
ユーザーオブジェクトは別のdb
に作成されているため、user
を更新しようとすると、現在のデータベースはこのuser
オブジェクトを認識しません。
ユーザーを取得することで解決できます
try
{
// or check on FirstName and LastName if you don't have a user id
var updatedUser = db.Users.SingleOrDefault(x => x.id == id);
updatedUser.FirstName = user.FirstName;
updatedUser.LastName = user.LastName;
db.Entry(updatedUser).State = EntityState.Modified;
db.SaveChanges();
}
または、user
オブジェクトの作成に使用しているデータコンテキストが、ユーザーを更新しようとしているものと同じであることを確認できます。
これは理にかなっていますか?
これは、リポジトリが異なるEntity Framework DbContextに動的にアクセスする必要がある場合、つまり異なるデータベースを意味する場合に常に発生しました。
各エンティティFrmework DbContextのweb.configファイルでデータ接続文字列を確認します。
例えば:
<add name="CRMEntities" connectionString="metadata=res://*/CRMEntities.csdl|res://*/CRMEntities.ssdl|res://*/CRMEntities.msl;provider=System.Data.SqlClient;provider connection string="data source=Your Data Source;initial catalog=CRM;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
connectionStringのメタデータが正しいDbContextを指している場合は確認してください。
この例では、「CRMEntities」というdemxファイルを指しています。
正しいメタデータ部分がedmxと同じであることを確認してください。
connectionString="metadata=res://*/Model1.csdl|res://*/Model1.ssdl|res://*/Model1.msl;"
モデルを更新して、IDプロパティを含めます。
それから
var e = db.Entry(user);
e.Property(p => p.FirstName).Modified = true;
プロパティ行は、個々のフィールドを指定する方法です。
ビューモデルは完全修飾ユーザーオブジェクトではありません。そのため、取得する必要があります。
この呼び出しdb.User.IsInRole("Admin")
は、現在のユーザーが既にいることを示しているようです。あなたはただそれを修正してから変更のためにそれを提出する必要があります
try
{
db.User.FirstName = user.FirstName;
db.User.LastName = user.LastName;
db.Entry(db.User).State = EntityState.Modified;
db.SaveChanges();
}
これは、誰かが既存のものから切り取って貼り付けることでapp.configに新しい接続文字列を作成したために起こりました。
結果は次のようになりました。
<connectionStrings>
<add
name="Db1Context"
connectionString="metadata=res://*/Db1Context.csdl|res://*/Db1Context.ssdl|res://*/Db1Context.msl;..."
providerName="System.Data.EntityClient"
/>
<add
name="Db2Context"
connectionString="metadata=res://*/Db1Context.csdl|res://*/Db1Context.ssdl|res://*/Db1Context.msl;..."
providerName="System.Data.EntityClient"
/>
</connectionStrings>
Db2ContextがメタデータでDbContext1を参照する方法に注意してください...
私もこの例外を取得しています。図でEntity.edmxモデルを右クリックし、「データベースからモデルを更新」を使用してデータベースへの接続を更新することで解決しました。
これがなぜ機能したのかはわかりませんが、少なくとも私の場合はそうでした。
クラスのインスタンスをDbSetに追加しようとしたときに、例外を受け取るのと同じ問題がありました。私の問題は、データベース内のテーブルの定義が実際のオブジェクトと一致しなかったことでした(2つの非nullプロパティがモデルにありませんでした)。クラスに2つのプロパティを追加すると、エラーはなくなりました。
私の場合、問題は対応するエンティティファイルに1つの列が存在しないことでした。 edmxには1つの列マッピングがありましたが、charpファイルにはありませんでした
サーバーが64または32ビットであることを確認し、アプリケーションを再コンパイルします。
同じ問題がありました。私の問題は、マッピングエンティティ/テーブルを配置しないことでした。エンティティをマッピングした後、問題は解決しました。