我有一个循环guid列表的方法,并通过DbContext将它们保存到数据库中。 B是WebObjects的DbSet集合(例如:DbSet<MlaPerson> MlaPersons
)
protected void AddRelatedWebObject<A, B>(A mlaObject, B inputObject, List<Guid> guids)
where A : WebObject
where B : DbSet<WebObject>
{
foreach (Guid guid in guids)
{
mlaObject.RelatedWebObjects.Add(inputObject.Find(guid));
_db.SaveChanges();
}
}
使用:
foreach (ArticleRelationships item in articleRelationships)
{
MlaArticle article = new MlaArticle();
article = _db.MlaArticles.Include(m => m.WebSite).Where(m => m.Id == item.ArticleId).First();
AddRelatedWebObject<MlaArticle, DbSet<MlaPerson>>(article, _db.MlaPersons, item.PersonIds);
}
_db.MlaPersons定义为:
public class ECM2Context : DbContext
{
public DbSet<MlaPerson> MlaPersons { get; set; }
}
,MlaPerson定义为:
public class MlaPerson : WebObject, IValidatableObject
{
...
}
我认为通过推断B是DbSet<WebObject>
会起作用,因为MlaPerson的基类是WebObject,但我错了。我收到了错误:
The type 'System.Data.Entity.DbSet<ExternalContentManager.Models.MlaPerson>' cannot be used as a type parameter 'B' in the generic type or method 'AddRelatedWebObjects'. There is not implicit reference conversion from 'System.Data.Entity.DbSet<ExternalContentManager.Models.MlaPerson>' to 'System.Data.Entity.DbSet<ExternalContentManager.Models.WebObject>'
我非常感谢所提供的任何和所有帮助。谢谢你的帮助。 乙
答案 0 :(得分:9)
您正在制作一个常见的泛型错误 - 假设集合是协变的。也就是说,即使汽车继承自车辆,List<Car>
的实例也不会从List<Vehicle>
继承。同样,即使MlaPerson继承自WebObject,DbSet<MlaPerson>
也不会从DbSet<WebObject>
继承。
你需要做的是这样的事情(我没有测试过这段代码):
protected void AddRelatedWebObject<A, B, O>(A mlaObject, B inputObject, List<Guid> guids)
where A : WebObject
where B : DbSet<O>
where O : WebObject
{
foreach (Guid guid in guids)
{
mlaObject.RelatedWebObjects.Add(inputObject.Find(guid));
_db.SaveChanges();
}
}
并使用它:
foreach (ArticleRelationships item in articleRelationships)
{
MlaArticle article = new MlaArticle();
article = _db.MlaArticles.Include(m => m.WebSite).Where(m => m.Id == item.ArticleId).First();
AddRelatedWebObject<MlaArticle, DbSet<MlaPerson>, MlaPerson>(article, _db.MlaPersons, item.PersonIds);
}
如果你这样做,你可以放弃类型规范(<MlaArticle, DbSet<MlaPerson>, MlaPerson>
),因为它应该推断它。
答案 1 :(得分:7)
DbSet<MlaPerson>
不是DbSet<WebObject>
只是因为MlaPerson
来自WebObject
。在Stack Overflow上搜索“generic variance”以找出原因。
您可能希望更改方法参数和约束,如下所示:
protected void AddRelatedWebObject<A, B>(A mlaObject, DbSet<B> inputObject,
List<Guid> guids)
where A : WebObject
where B : WebObject
然后像这样称呼它:
AddRelatedWebObject<MlaArticle, MlaPerson>(article, _db.MlaPersons,
item.PersonIds);
这可能有用 - 它甚至可以使用类型推断来实现:
AddRelatedWebObject(article, _db.MlaPersons, item.PersonIds);
我还建议您将类型参数重命名为TSource
和TTarget
,以便更清楚,并遵循惯例。
答案 2 :(得分:0)
- 编辑 - 这个答案是错的。请参阅评论以获取更多信息 -
向上转换不适用于容器(除非您正在向上转换数据结构,但这不是这种情况)。想象一下下面的代码(为简单起见用数组编写,但相同的原则适用于所有通用容器):
class A{}
class B:A{}
/*Inside a method*/
B[] arrayB=new B[10];
A[] arrayA=arrayB;//This line will produce a compile error
arrayA[0]=new A();
现在arrayB[0]
包含A类型的对象,即使它A
不是B
的派生类。这就是为什么向上转换不适用于容器。