C# 并创建了一个修复程序。谢谢你一直思考!通常,为了避免这种异常,在EF实体上公开FK属性通常是一个好做法。不过,您仍然应该在实体上实现IEquatable接口,因为它处理的集合太多,而动态代理意味着ReferenceEquals比较将返回false。 pub
C# 并创建了一个修复程序。谢谢你一直思考!通常,为了避免这种异常,在EF实体上公开FK属性通常是一个好做法。不过,您仍然应该在实体上实现IEquatable接口,因为它处理的集合太多,而动态代理意味着ReferenceEquals比较将返回false。 pub,c#,entity-framework,entity-framework-6,C#,Entity Framework,Entity Framework 6,并创建了一个修复程序。谢谢你一直思考!通常,为了避免这种异常,在EF实体上公开FK属性通常是一个好做法。不过,您仍然应该在实体上实现IEquatable接口,因为它处理的集合太多,而动态代理意味着ReferenceEquals比较将返回false。 public class Language { [JsonProperty("iso_639_1")] public string Iso { get; set; } [JsonProperty("name")] p
并创建了一个修复程序。谢谢你一直思考!通常,为了避免这种异常,在EF实体上公开FK属性通常是一个好做法。不过,您仍然应该在实体上实现
IEquatable
接口,因为它处理的集合太多,而动态代理意味着ReferenceEquals比较将返回false。
public class Language
{
[JsonProperty("iso_639_1")]
public string Iso { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
public override bool Equals(object obj)
{
if (!(obj is Language))
{
return false;
}
return ((Language)obj).Iso == Iso;
}
public override int GetHashCode()
{
return Iso.GetHashCode();
}
}
var localLanguages = context.Languages.ToList();
var existingLanguages = localLanguages.Union(movie.SpokenLanguages);
var newLanguages = localLanguages.Except(existingLanguages).ToList();
newLanguages.AddRange(existingLanguages);
movie.SpokenLanguages = newLanguages;
var localLanguages = context.Languages.ToList();
foreach (var language in movie.SpokenLanguages)
{
if (localLanguages.Contains(language))
{
context.Languages.Attach(language);
// no difference between both approaches
context.Entry(language).State = EntityState.Unchanged;
}
}
{
"iso_639_1": "en",
"name": "English"
}
public class Language : IEquatable<Language>
{
[JsonProperty("iso_639_1")]
public string Iso { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
public override bool Equals(object obj)
{
return Equals(other as Language);
}
public bool Equals(Langauge other)
{
// instance is never equal to null
if (other == null) return false;
// when references are equal, they are the same object
if (ReferenceEquals(this, other)) return true;
// when either object is transient or the id's are not equal, return false
if (IsTransient(this) || IsTransient(other) ||
!Equals(Iso, other.Iso)) return false;
// when the id's are equal and neither object is transient
// return true when one can be cast to the other
// because this entity could be generated by a proxy
var otherType = other.GetUnproxiedType();
var thisType = GetUnproxiedType();
return thisType.IsAssignableFrom(otherType) ||
otherType.IsAssignableFrom(thisType);
}
public override int GetHashCode()
{
return Iso.GetHashCode();
}
private static bool IsTransient(Language obj)
{
// an object is transient when its id is the default
// (null for strings or 0 for numbers)
return Equals(obj.Iso, default(string));
}
private Type GetUnproxiedType()
{
return GetType(); // return the unproxied type of the object
}
}
var localLanguages = context.Languages.ToList(); // dynamic proxies
foreach (var language in movie.SpokenLanguages) // non-proxied
{
if (localLanguages.Any(x => x.Equals(language)))
{
context.Entry(language).State = EntityState.Modified;
}
}
INSERT [dbo].[MovieLanguages]([MovieId], [LanguageId])
VALUES (@0, @1)
-- @0: '2' (Type = Int32)
-- @1: '0' (Type = Int32)
var localLanguages = _context.Languages.ToList();
foreach (var language in movie.SpokenLanguages)
{
var localLanguage = localLanguages.Find(x => x.Iso == language.Iso);
if (localLanguage != null)
{
language.Id = localLanguage.Id;
_context.Entry(localLanguage).State = EntityState.Detached;
_context.Languages.Attach(language);
}
}