vs 快捷键 Ctrl+"." 建议 Ctrl+"j" 说明 Ctrl+"]" 匹配分支
ObjectContext
contains all of the methods necessary to work against the database, such as CreateDatabase, SaveChanges, and more [see (https://docs.microsoft.com/en-us/dotnet/api/system.data.entity.core.objects.objectcontext?view=entity-framework-6.2.0) for more information
DbContext
DBContext contains all of the critical methods necessary to work against the database。 a lot of the underlying patterns are implemented by default and don’t require manual intervention from developers
The official documentation (https://docs.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.dbcontext?view=efcore-6.0
DbContext实现了两种模式
the unit of work (UoW) pattern, and the repository design pattern
仓储(Repository)
- 仓储(Respository)
是存在于工作单元和数据库之间单独分离出来的一层,是对数据访问的封装。 对于非泛型的仓储实现等同于DAL层。 - 工作单元
工作单元的定义是:维护一个受业务事务影响的对象列表,并协调写入更改内容和并发问题的解决方案。
一个业务事务中,可能需要多次修改对象模型,对象模型的修改需要记录到数据库中,当然可以每次对象模型有修改时就将变化记录到数据库中,但是这会产生很多对数据库的调用。而使用工作单元来记录业务事务中对数据库有影响的所有变化,就可以减少对数据库的大量小规模调用。
很显然对象模型的变化,工作单元都必须知道并且记录。所以一旦有变化产生都必须通知工作单元,
原文链接:(https://blog.csdn.net/iteye_4565/article/details/82484927)
在进行数据库添加、修改、删除时,为了保证事务的一致性,即操作要么全部成功,要么全部失败。例如银行A、B两个账户的转账业务。一方失败都会导致事务的不完整性,从而事务回滚。而工作单元模式可以跟踪事务,在操作完成时对事务进行统一提交。
using the DBContext, we don’t have to explicitly manage simple transactions when working with the DBContext, as they will be handled by the context implementing the UoW pattern.
all operations are pending and not applied until an explicit call is made to SaveChanges. If something fails during that final call to SaveChanges, the entire modified set is rolled back, which can be both a blessing and a curse for developers
dbcontext 构造函数
传递DBContextOptions 通过重写OnConfiguring 实现 any creation of the DBContext will use the OnConfiguring method,so we can continue to modify the options for our
DBContext
- 带参
- 不带参
DBSet<TEntity> CRUD operations.
database first
- Create the model as a C# .Net class to generate a table.
- Add public properties to the model with a data type and a name for fields.
- Add the entity to the DBContext (if not already there) as DBSet<TEntity> where TEntity is the type of your model. If the model is already in the DBContext, skip this and proceed to Step 4.
- Generate a new code-first migration to apply the modeled changes using the add-migration command.
- Update the database using the update-database command.
public DateTime? PurchasedDate { get; set; } 数据表项允许为空
public DateTime SoldDate { get; set; } 数据表项不允许为空
Strings and other nullable types are defaulted as nullable in the database
SaveChanges( ) 重写此方法可以检索并修改将要执行的项目。
default operation take place by overriding the SaveChanges method.
public override int SaveChanges()
{
var tracker = ChangeTracker;
foreach (var entry in tracker.Entries())
{
System.Diagnostics.Debug.WriteLine($"{entry.Entity} has state {entry.State}");
}
return base.SaveChanges();
}
The valid states are Added, Deleted, Detached, Modified, and Unchanged
数据类型 annotation using System.ComponentModel.DataAnnotations
your string fields have NVARCHAR(MAX) one billion characters
- NVARCHAR allows for unicode characters,
- VARCHAR only stores non-unicode characters.
- [Required]
- [StringLength(<size, int>)]
[StringLength(InventoryModelsConstants.MAX_NOTES_LENGTH, MinimumLength = 10)] - [Range(0, int.MaxValue)]
[Range(InventoryModelsConstants.MINIMUM_QUANTITY, InventoryModelsConstants.MAXIMUM_QUANTITY)] - [DefaultValue(<the_value>)]
[DefaultValue(false)] The DefaultValue requires bringing in the using statement using System.ComponentModel; - [Key] attribute with a column order [Column(Order=n)] (the order groups the keys).
- [Index]
add-migration updateItem_enforceStringMaxLength
add-migration updateItems_setMinMaxValuesOnQuantityAndPrice.
relationship 关系 一对一 一对多 多对多
[ForeignKey("CategoryId")]
在使用EF中我们会使用导航属性,其中会加上Virtual关键字 ,加了此关键字就可以使用lazyload懒加载,不加此特性的话是加载不出此导航属性的内容的。
(实体之间的关联属性又叫做“导航属性(Navigation Property)”)
如果public virtual Class Class { get; set; }(实体之间的关联属性又叫做“导航属性(Navigation Property)”)把virtual 去掉,那么下面的代码就会报空引用异常
var s = ctx.Students.First();
Console.WriteLine(s.Class.Name);
联想为什么?凭什么!!! 改成virtual观察SQL的执行。执行了两个SQL,先查询T_Students,再到T_Classes中查到对应的行。 这叫“延迟加载”(LazyLoad),只有用到关联的对象的数据,才会再去执行select 查询。注意延迟加载只在关联对象属性上,普通属性没这个东西。
1.Installing the Microsoft.EntityFrameworkCore.Design package
2.Open the Package Manager Console in VS and select the project in the dropdown to set the starter project as the target for the operation.
3,Scaffold-DbContext "DataSource = .\database\sysrecord.db3" Microsoft.EntityFrameworkCore.Sqlite
scaffold "Filename=Northwind.db" Microsoft.EntityFrameworkCore.Sqlite --table Categories --table Products --outputdir AutoGenModels --namespace WorkingWithEFCore.AutoGen --data-annotations
--context N
orthwind
Scaffold-DbContext "data source = yourdbname" Microsoft.EntityFrameworkCore.Sqlite -OutputDir Models -f
private static IConfigurationRoot _configuration;
private static DbContextOptionsBuilder<InventoryDbContext> _optionsBuilder;
static void Main(string[] args)
{
BuildConfiguration();
// BuildOptions();
BuildOptions1();
}
static void BuildOptions()
{
_configuration = ConfigurationBuilderSingleton.ConfigurationRoot;
}
static void BuildConfiguration()
{
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
_configuration = builder.Build();
}
static void BuildOptions1()
{
_optionsBuilder = new DbContextOptionsBuilder<InventoryDbContext>();
_optionsBuilder.UseSqlite(_configuration.GetConnectionString("sqliteconnectstring"));
}
static void ListPeople()
{
using (var db = new AdventureWorksContext(_optionsBuilder.Options))
{
var people = db.People.OrderByDescending(x => x.LastName).Take(20).
ToList();
foreach (var person in people)
{
Console.WriteLine($"{person.FirstName} {person.LastName}");
}
}
}
public class InventoryDbContext : DbContext
{
private static IConfigurationRoot _configuration;
public DbSet<Item> Items { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
_configuration = builder.Build();
var cnstr = _configuration.GetConnectionString("sqliteconnectstring");
// cnstr = "DataSource = .\database\sysItem.db3";
optionsBuilder.UseSqlite(cnstr);
}
}
public InventoryDbContext()
{
}
public InventoryDbContext(DbContextOptions options) : base(options)
{
}
}
private static void DeleteAllItems()
{
using (var db = new InventoryDbContext(_optionsBuilder.Options))
{
var items = db.Items.ToList();
db.Items.RemoveRange(items);
db.SaveChanges();
}
}
add-migration updated_items_table
add-migration initial_setup_create_items_table
Update-Database