Sha*_*ark 5 c# sqlite entity-framework-core .net-core
我正在学习实体框架核心,将它与 SQLITE 一起使用我在数据库中有 2 个表。
留言:
CREATE TABLE `Messages` (
`Id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
`IsDeleted` INTEGER NOT NULL,
`FromUserId` INTEGER,
`ToUserId` INTEGER,
`SendDate` TEXT NOT NULL,
`ReadDate` TEXT NOT NULL,
`MessageContent` TEXT,
CONSTRAINT `FK_Messages_Users_ToUserId` FOREIGN KEY(`ToUserId`) REFERENCES `Users`(`Id`) ON DELETE RESTRICT,
CONSTRAINT `FK_Messages_Users_FromUserId` FOREIGN KEY(`FromUserId`) REFERENCES `Users`(`Id`) ON DELETE RESTRICT
);
Run Code Online (Sandbox Code Playgroud)
和用户表:
CREATE TABLE `Users` (
`Id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
`IsDeleted` INTEGER NOT NULL,
`Name` TEXT,
`DisplayName` TEXT,
`Gender` INTEGER NOT NULL,
`BirthDate` TEXT NOT NULL
);
Run Code Online (Sandbox Code Playgroud)
我的 C# 类看起来像:
public class User
{
public int Id {get;set;}
public bool IsDeleted{get;set;}
[Required]
public string Name{get;set;}
public string DisplayName{get;set;}
[Required]
public char Gender{get;set;}
[Required]
public DateTime BirthDate{get;set;}
public User(string n, string dn, char g, DateTime bd)
{
Name=n; DisplayName = dn; Gender = g; BirthDate = bd;
}
protected User(){}
public override string ToString()
{
return string.Format("{0} ({1}) {2}", this.Name, this.Gender,this.BirthDate.ToShortDateString());
}
}
Run Code Online (Sandbox Code Playgroud)
和消息类:
public class Message
{
public int Id{get;set;}
public bool IsDeleted{get;set;}
[Required]
public Users.User FromUser{get;set;}
[Required]
public Users.User ToUser{get;set;}
[Required]
public DateTime SendDate{get;set;}
public DateTime? ReadDate{get;set;}
[Required]
public string MessageContent{get;set;}
protected Message(){}
public Message(User from, User to, string content)
{
this.FromUser = from;
this.ToUser = to;
this.MessageContent = content;
this.SendDate = DateTime.Now;
this.ReadDate = DateTime.Now;
}
}
Run Code Online (Sandbox Code Playgroud)
users 表有效,但是当我尝试通过以下方式向消息添加新实体时:
public override int Insert(Message entity)
{
dbc.Messages.Add(entity);
dbc.SaveChanges();
return entity.Id;
}
Run Code Online (Sandbox Code Playgroud)
我收到以下错误:
SQLite 错误 19:'唯一约束失败
我不知道出了什么问题。当我手动将数据插入数据库(使用数据库浏览器进行 sqlite)时,它可以工作。班级关系好吗?
我的dbContextSnapshot是:
[DbContext(typeof(RandevouDbContext))]
partial class RandevouDbContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder.HasAnnotation("ProductVersion", "2.1.4-rtm-31024");
modelBuilder.Entity("RandevouData.Messages.Message", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<int>("FromUserId");
b.Property<bool>("IsDeleted");
b.Property<string>("MessageContent")
.IsRequired();
b.Property<DateTime?>("ReadDate");
b.Property<DateTime>("SendDate");
b.Property<int>("ToUserId");
b.HasKey("Id");
b.HasIndex("FromUserId");
b.HasIndex("ToUserId");
b.ToTable("Messages");
});
modelBuilder.Entity("RandevouData.Users.User", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<DateTime>("BirthDate");
b.Property<string>("DisplayName");
b.Property<char>("Gender");
b.Property<bool>("IsDeleted");
b.Property<string>("Name")
.IsRequired();
b.HasKey("Id");
b.ToTable("Users");
});
modelBuilder.Entity("RandevouData.Messages.Message", b =>
{
b.HasOne("RandevouData.Users.User", "FromUser")
.WithMany()
.HasForeignKey("FromUserId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("RandevouData.Users.User", "ToUser")
.WithMany()
.HasForeignKey("ToUserId")
.OnDelete(DeleteBehavior.Cascade);
});
#pragma warning restore 612, 618
}
Run Code Online (Sandbox Code Playgroud)
顺便一提。我无法从两侧配置映射。
Message 实体有 UserFrom 和 UserTo 字段,但 User 实体不能有 Messages,因为有时他是“userFrom”,而其他时候他可以是“userTo”。
还有一个代码,我在其中创建消息实体
public int SendMessage(int senderId, int receiverId, string content)
{
var dao = new MessagesDao();
var usersDao = new UsersDao();
var userService = new UserService(mapper);
var sender = usersDao.Get(senderId);
var receiver = usersDao.Get(receiverId);
var entity = new Message(sender,receiver,content);
var id = dao.Insert(entity);
return id;
}
Run Code Online (Sandbox Code Playgroud)
我覆盖 GET 方法的用户 dao
public override User Get(int id)
{
using (var context = new RandevouDbContext())
{
var user = dbc.Find<User>(id);
return user;
}
}
Run Code Online (Sandbox Code Playgroud)
和 MessagesDao 在那里我覆盖了 Add 方法
public override int Insert(Message entity)
{
using (var dc = new RandevouDbContext())
{
dc.Messages.Add(entity);
dc.SaveChanges();
return entity.Id;
}
}
Run Code Online (Sandbox Code Playgroud)
要修复“UNIQUE”约束异常,您需要确保您正在使用的所有实体都被您要保存到的上下文跟踪。
例如
// Get user from one context
User thisUser = db.Users.Find(3);
//Now imagine you have another context which has been created later on
DbContext newContext = new DbContext();
//and you want to create a message, assign it to your user
//and save it to the new context
Message newMessage = new Message
{
Text = "Hello",
User = thisUser
}
newContext.Messages.Add(newMessage);
// saving this to newContext will fail because newContext is not tracking thisUser,
// Therefore attach it...
newContext.Users.Attach(thisUser).
//now newContext is tracking thisUser *AND* newMessage, so the save operation will work
newContext.SaveChanges();
Run Code Online (Sandbox Code Playgroud)
好的,我解决了问题。阅读一些关于 EF DbContext 的文章。当我为 GET User 和 CREATE 消息使用其他两个上下文时,实体(user1 和 user2)与我用于第二个上下文的实体不同。我的意思是,实体是一样的,但他们有另一个跟踪
EF Core / Sqlite 一对多关系在唯一索引约束上失败
所以我通过在一个业务事务(而不是一个数据库事务)上使用一个上下文来解决问题。只是将创建上下文移动到业务逻辑,Generic dao 类正在等待构造函数中的上下文,如下所示:
public class MessagesDao : BasicDao<Message>
{
public MessagesDao(RandevouDbContext dbc) : base(dbc)
{
}
public IQueryable<Message> QueryMessages()
{
return dbc.Messages.AsQueryable();
}
public override int Insert(Message entity)
{
dbc.Messages.Add(entity);
dbc.SaveChanges();
return entity.Id;
}
}
public abstract class BasicDao<TEntity> where TEntity : BasicRandevouObject
{
protected RandevouDbContext dbc;
public BasicDao(RandevouDbContext dbc) { this.dbc = dbc; }
public virtual int Insert(TEntity entity)
{
dbc.Add<TEntity>(entity);
dbc.SaveChanges();
return entity.Id;
}
public virtual void Update(TEntity entity)
{
dbc.Update(entity);
dbc.SaveChanges();
}
public virtual void Delete(TEntity entity)
{
dbc.Remove(entity);
dbc.SaveChanges();
}
public virtual TEntity Get(int id)
{
var entity = dbc.Find<TEntity>(id);
return entity;
}
}
Run Code Online (Sandbox Code Playgroud)
并在业务逻辑代码中:
public int SendMessage(int senderId, int receiverId, string content)
{
using (var dbc = new RandevouDbContext())
{
var dao = new MessagesDao(dbc);
var usersDao = new UsersDao(dbc);
var userService = new UserService(mapper);
var sender = usersDao.Get(senderId);
var receiver = usersDao.Get(receiverId);
var entity = new Message(sender,receiver,content);
var id = dao.Insert(entity);
return id;
}
}
Run Code Online (Sandbox Code Playgroud)
现在一切正常。顺便说一下,它仍然是脏代码,因为我只是在尝试一些东西,但我希望如果有人遇到类似的问题,那么他会找到这篇文章。
您的(非常详细的)问题中缺少的是Message您传递给Insert(). 您之前是否将这两个保存User到数据库中,或者它们也是两个新对象?如果它们是新的,那么它们的 ID 应该为零,以便 EF 在创建Message.
| 归档时间: |
|
| 查看次数: |
13678 次 |
| 最近记录: |