Dav*_*Dev 6 c# entity-framework
我正在尝试对Advertisement包含一个对象的对象进行Upsert List<AdImage>.该Advertisement包含对应于一个外键User.A user可以具有零或更多Advertisements,并且Advertisement具有一个或多个AdImages.
upsert失败,并带有以下内容:
保存不公开其关系的外键属性的实体时发生错误.EntityEntries属性将返回null,因为无法将单个实体标识为异常的来源.通过在实体类型中公开外键属性,可以更轻松地在保存时处理异常.有关详细信息,请参阅InnerException.
内在的例外是:
无法确定相关操作的有效排序.由于外键约束,模型要求或存储生成的值,可能存在依赖关系.
该advertisement实例化非常简单的:
var ad = new Advertisement
{
AdImages = new List<AdImage>
{
new AdImage {Image = model.Image}
},
Message = model.Message,
Title = model.Title,
User = user,
};
_aAdAppService.UpsertAdvertisement(ad);
Run Code Online (Sandbox Code Playgroud)
有问题的实体定义为:
public class User : AbpUser<Tenant, User>
{ // AbpUser is a 3rd party class which defines Id as a primary key
public string AccessToken { get; set; }
public long UserId { get; set; }
public virtual List<Advertisement> Advertisements { get; set; }
}
public class Advertisement : Entity
{
[Key]
public long Id { get; set; }
public string Title { get; set; }
public string Message { get; set; }
public List<AdImage> AdImages { get; set; }
public virtual User User { get; set; }
}
public class AdImage : Entity
{
[Key]
public int Id { get; set; }
public string Image { get; set; }
public virtual Advertisement Advertisement { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
这就是定义关系的方式:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<User>()
.HasMany(u => u.Advertisements)
.WithRequired(x => x.User);
modelBuilder.Entity<Advertisement>()
.HasMany(a => a.AdImages)
.WithRequired(x => x.Advertisement);
modelBuilder.Entity<AdImage>()
.HasRequired(x => x.Advertisement);
base.OnModelCreating(modelBuilder);
}
Run Code Online (Sandbox Code Playgroud)
错误消息是什么意思?我看不出我的关系是如何被错误定义的.我该如何解决这个问题?
解决方案是将我的端点包装在UnitOfWork. 我不太熟悉实体框架的经文,无法准确描述问题或为什么它有效,但它确实有效。
这是一个有效的示例(尽管与上面的示例代码略有不同):
[UnitOfWork]
public async void Post(AdvertisementVM model)
{
CheckModelState();
try
{
if (_unitOfWorkManager.Current == null)
{
using (var mgr = _unitOfWorkManager.Begin())
{
await ExecuteMultipleDatabaseCalls(model);
await mgr.CompleteAsync();
}
}
else
{
await ExecuteMultipleDatabaseCalls(model);
}
}
catch (Exception ex)
{
throw new HttpException((int)HttpStatusCode.InternalServerError, ex.Message);
}
}
private async Task ExecuteMultipleDatabaseCalls(AdvertisementVM model)
{
var retailer = _retailerAppService.GetForUser(model.UserId);
var ad = new Advertisement
{
Message = model.Message,
Title = model.Title,
Retailer = retailer
};
await _adAppService.InsertOrUpdate(ad);
await _unitOfWorkManager.Current.SaveChangesAsync();
}
Run Code Online (Sandbox Code Playgroud)
该UnitOfWork属性是 ASP.NET Boilerplate 项目的成员,其定义如下:
摘要: 该属性用于指示声明方法是原子的并且应被视为一个工作单元。具有此属性的方法将被拦截,在调用该方法之前打开数据库连接并启动事务。在方法调用结束时,如果没有异常,则提交事务并将所有更改应用于数据库,否则将回滚。
备注: 如果在调用该方法之前已经存在工作单元,则该属性无效,如果存在,则使用相同的事务。
| 归档时间: |
|
| 查看次数: |
1259 次 |
| 最近记录: |