企业商城网站开发建设网站开发与应用论文

张小明 2025/12/29 8:55:24
企业商城网站开发建设,网站开发与应用论文,傻瓜网页制作工具,阜阳网页多”关系不像“一对多”那么“单纯”#xff0c;它内部涉及到“连接实体”#xff08;Join Entity#xff09;的概念。咱们先放下这个概念不表#xff0c;来了解一下多对多数据表为什么需要一个“辅助表”来建立关系。假设有两张表#xff1a;一张表示学生#xff0c;一张…多”关系不像“一对多”那么“单纯”它内部涉及到“连接实体”Join Entity的概念。咱们先放下这个概念不表来了解一下多对多数据表为什么需要一个“辅助表”来建立关系。假设有两张表一张表示学生一张表示选修课。那么这里头的关系是你可以选多门课而一门课可以被多人选。这是多对多关系没问题吧。image按照数据库存储的原则学生表中每位学生的信息都不应重复而课程表也是如此。这么一看多对多的关系不能直接在这两个表中创建了。那就只能引入第三个表专门保存前两个表的信息了。image经过这样处理后多对多的关系被拆解成两个一对多关系左边学生1--- 中间表N右边课程1--- 中间表N。这个中间表负责”连接“两个数据表。转换为实体类开这个中间表就是”连接实体“了。------------------------------------------------------------------------------------------------------------------------接下来先弄个开胃菜一个很简单的例子1、定义实体。复制代码public class Student{public int Id { get; set; }public string Name { get; set; } null!;public string Code { get; set; } null!;public string? Email { get; set; }// 注意这个属性public IListCourse SelectedCourses { get; set; } new ListCourse();}public class Course{public Guid Id { get; set; }public string Name { get; set; } null!;public string? Tags { get; set; }// 注意这个属性public IListStudent Students { get; set; } new ListStudent();}复制代码实体类没什么就是一个学生类一个课程类。不过请留意一下被标记的属性后面会考。2、定义数据库上下文。复制代码public class TestContext : DbContext{protected override void OnConfiguring(DbContextOptionsBuilder ob){ob.UseSqlServer(server(localdb)\\mssqllocaldb;databaseMySchool);}#region 数据集合public DbSetStudent StudentSet { get; set; }public DbSetCourse CourseSet { get; set; }#endregion}复制代码上下文这样就可以了这里可以不写配置数据库模型的代码因为 EF Core 内置的约定类会帮我们自动完成。a、通过 DbContext 或子类定义的 DbSet 类型的属性自动向模型添加 Student、Course 实体b、通过上面标记的特殊属性你看考点来了自动识别出这是多对多的关系。Student 类的 SelectedCourses 属性导航到 CourseCourse 类的 Students 属性导航到 Student。两个导航属性都是集合类型因此两者的关系是多对多。此处SelectedCourses 和 Students 属性有个专用名字叫“跳跃导航”Skip Navigation。这里不应该翻译为“跳过导航”因为那样翻译意思就不太好理解所以应取“跳跃”。解释一下为什么会跳跃。还记得前文的分析吗两个表如果是多对多关系那么它们需要一个“连接”表来存储对应关系。也就是说正常情况下Student 类的导航属性应该指向中间实体映射到连接表Course 实体的导航属性也应该指向中间实体再通过中间实体把二者连接起来。可是我们再回头看看示例Student 的导航属性直接指向了 Course而 Course 实体的导航属性也直接指向了 Student 实体。即它们都跨过跳过中间实体两者直接连接起来了。老周画了一个不专业的简图。image这里也产生了一个疑问我们没创建中间实体啊难道是 EF Core 帮我们创建了还真是不妨打印一下数据库模型。复制代码static void Main(string[] args){using var context new TestContext();// 获取数据库模型IModel model context.Model;// 打印Console.WriteLine(model.ToDebugString());}复制代码然后运行代码看看输出什么。复制代码Model:EntityType: CourseProperties:Id (Guid) Required PK AfterSave:Throw ValueGenerated.OnAddName (string) RequiredTags (string)Skip navigations:Students (IListStudent) CollectionStudent Inverse: SelectedCoursesKeys:Id PKEntityType: CourseStudent (Dictionarystring, object) CLR Type: Dictionarystring, objectProperties:SelectedCoursesId (no field, Guid) Indexer Required PK FK AfterSave:ThrowStudentsId (no field, int) Indexer Required PK FK Index AfterSave:ThrowKeys:SelectedCoursesId, StudentsId PKForeign keys:CourseStudent (Dictionarystring, object) {SelectedCoursesId} - Course {Id} Required CascadeCourseStudent (Dictionarystring, object) {StudentsId} - Student {Id} Required CascadeIndexes:StudentsIdEntityType: StudentProperties:Id (int) Required PK AfterSave:Throw ValueGenerated.OnAddCode (string) RequiredEmail (string)Name (string) RequiredSkip navigations:SelectedCourses (IListCourse) CollectionCourse Inverse: StudentsKeys:Id PK复制代码有没有发现多了一个实体叫 CourseStudent。虽然我们在代码中没有定义这样的类但 EF Core 的 ManyToManyJoinEntityTypeConvention 约定类会自动给数据库模型添加一个实体类型是共享的 Dictionarystring, object。这可是个万能实体类型当你不想给项目定义一堆实体类时你甚至可以把所有实体全注册为字典类型。当然这样做对于面向对象对阅读你代码的人来说就不友好了。复制代码protected virtual void CreateJoinEntityType(string joinEntityTypeName,IConventionSkipNavigation skipNavigation){var model skipNavigation.DeclaringEntityType.Model;// DefaultPropertyBagType 就是字典类型var joinEntityTypeBuilder model.Builder.SharedTypeEntity(joinEntityTypeName, Model.DefaultPropertyBagType)!;var inverseSkipNavigation skipNavigation.Inverse!;CreateSkipNavigationForeignKey(skipNavigation, joinEntityTypeBuilder);CreateSkipNavigationForeignKey(inverseSkipNavigation, joinEntityTypeBuilder);}复制代码可以看看 DefaultPropertyBagType 字段在 Model 类中的定义Model 类从用途上不对外公开但类本身是 public 的。public static readonly Type DefaultPropertyBagType typeof(Dictionarystring, object);那这个自动添加的中间实体怎么命名呢继续看源代码。复制代码protected virtual string GenerateJoinTypeName(IConventionSkipNavigation skipNavigation){var inverseSkipNavigation skipNavigation.Inverse;Check.DebugAssert(inverseSkipNavigation?.Inverse skipNavigation,Inverses inverse should be the original skip navigation);var declaringEntityType skipNavigation.DeclaringEntityType;var inverseEntityType inverseSkipNavigation.DeclaringEntityType;var model declaringEntityType.Model;var joinEntityTypeName !declaringEntityType.HasSharedClrType? declaringEntityType.ClrType.ShortDisplayName(): declaringEntityType.ShortName();var inverseName !inverseEntityType.HasSharedClrType? inverseEntityType.ClrType.ShortDisplayName(): inverseEntityType.ShortName();joinEntityTypeName StringComparer.Ordinal.Compare(joinEntityTypeName, inverseName) 0? joinEntityTypeName inverseName: inverseName joinEntityTypeName;if (model.FindEntityType(joinEntityTypeName) ! null){var otherIdentifiers model.GetEntityTypes().ToDictionary(et et.Name, _ 0);joinEntityTypeName Uniquifier.Uniquify(joinEntityTypeName,otherIdentifiers,int.MaxValue);}return joinEntityTypeName;}复制代码乱七八糟一大段总结起来就是1、分别获取跳跃导航两端的类型即多对多关系中的两实体Student 和 Course2、将两实体的名称按字符排序排在前面的作为前半段名字排序在后面的作为后半段名字。比如Student 与 Course 排序字母 C 在 S 前面所以中间实体的名字就是 CourseStudent3、向中间实体添加两个属性两个属性共同构成主键。同时它们也是外键一个指向 Student一个指向 Course。即这两个属性同时是主键和外键。从中间实体到 Student 的导航叫“左边”从中间实体到 Course 实体的导航叫 “右边”。如果咱们不想用 EF Core 约定的中间实体也可以自己去定义。public class StudentCourseJoin{public Student TheStudent { get; set; } null!;public Course TheCourse { get; set; } null!;}有大伙伴会说了你这实体没有作为外键的属性啊。没事外键属性可以作为影子属性Shadow Property来添加反正有 TheStudent 等导航属性不需要借助外键属性也可以引用其实体。下面是非常复杂的配置代码各位可以先让时间停止然后慢慢看。复制代码public class TestContext : DbContext{……protected override void OnModelCreating(ModelBuilder modelBuilder){modelBuilder.EntityStudent()// 一个学生选多门课.HasMany(s s.SelectedCourses)// 一门课多位学生选.WithMany(c c.Students)// 中间实体.UsingEntityStudentCourseJoin(// 右边StudentCourseJoin Course// 一个 StudentCourseJoin 只引用一个 Courseright right.HasOne(e e.TheCourse)// 一个Course可引用多个StudentCourseJoin// 但此处省略了.WithMany()// 外键.HasForeignKey(Course_ID),// 左边StudentCourseJoin Student// 一个StudentCourseJoin引用一个Studentleft left.HasOne(e e.TheStudent)// 一个Student可引用多个StudentCourseJoin// 但这里省略了.WithMany()// 外键.HasForeignKey(Student_ID),ent {// 因为这两个是影子属性必须显式配置// 否则找不到属性会报错ent.Propertyint(Student_ID);ent.PropertyGuid(Course_ID);// 两个属性都是主键ent.HasKey(Student_ID, Course_ID);});}}复制代码最外层调用 modelBuilder.EntityStudent() 的代码就是配置 Student 和 Course 的关系的相信各位都懂的。复杂的部分是 UsingEntity 方法开始的配置中间实体连接实体的。首先咱们把中间实体的关系拆开A、Student 对中间实体一对多左边B、Course 对中间实体一对多右边。所以UsingEntity 方法的第一个委托配置右边。right right.HasOne(e e.TheCourse)// 一个Course可引用多个StudentCourseJoin// 但此处省略了.WithMany()// 外键.HasForeignKey(Course_ID)不要问为什么因为微软定义这个方法就是先右后左的。HasOne 就是从中间实体StudentCourseJoin出发它引用了几个 Course一个吧嗯所以是One嘛然后 WithMany 反过来Curse 可以引用几个中间实体多个吧不明白的可以想想中间表里面是不是可以重复出现课程。因为 Course 类没有定义导航属性去引用中间实体所以 WithMany 参数空白。最后是设置外键谁引用谁是中间实体引用 Course 吧所以需要一个叫 Course_ID 属性来保存课程ID。好了右边干完了到左边了。left left.HasOne(e e.TheStudent)// 一个Student可引用多个StudentCourseJoin// 但这里省略了.WithMany()// 外键.HasForeignKey(Student_ID)左边是谁跟谁从中间实体出发它可以引用几个 Student一个吧所以是 HasOne反过来Student 可以引用几个中间实体由于学生可以多次出现在中间实体中所以是 WithMany但 Student 类没有指向中间实体的导航属性所以参数空。最后是外键谁引用谁是中间实体引用 Student 类吧所以中间实体要有一个 Student_ID 属性来保存学生ID。可是Student_ID 和 Course_ID 在中间实体中是没有定义的属性如果不手动配置EF Core 是找不到的。复制代码ent {// 因为这两个是影子属性必须显式配置// 否则找不到属性会报错ent.Propertyint(Student_ID);ent.PropertyGuid(Course_ID);// 两个属性都是主键ent.HasKey(Student_ID, Course_ID);}复制代码这两个属性因为实体类中没有定义所以要作为影子属性用然后是两个属性都是主键。完事了。
版权声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

一个网站如何挣钱代理记账公司注册

第一章:Rust-PHP 扩展的版本适配在构建基于 Rust 编写的 PHP 扩展时,版本兼容性是确保扩展稳定运行的关键因素。PHP 的内部 API 随版本迭代频繁变化,而 Rust 通过 php-rs 或 ext-php-rs 等绑定库与 Zend 引擎交互,因此必须精确匹配…

张小明 2025/12/26 12:20:44 网站建设

ipad网站制作头像设计免费

OpenVSCode Server性能调优实战:资源管理与高效配置指南 【免费下载链接】openvscode-server 项目地址: https://gitcode.com/gh_mirrors/op/openvscode-server 在云端开发环境日益普及的今天,OpenVSCode Server作为基于浏览器的代码编辑器服务器…

张小明 2025/12/26 12:20:10 网站建设

申请自助建站做互联网的网站

无损视频剪辑终极指南:如何用LosslessCut实现专业级编辑 【免费下载链接】lossless-cut The swiss army knife of lossless video/audio editing 项目地址: https://gitcode.com/gh_mirrors/lo/lossless-cut 还在为视频剪辑后画质下降而烦恼?传统…

张小明 2025/12/26 12:19:37 网站建设

最好的网站代运营公司教学网站系统流程图

跨平台资源监控UI设计:从零构建专业级监控界面 【免费下载链接】compose-multiplatform JetBrains/compose-multiplatform: 是 JetBrains 开发的一个跨平台的 UI 工具库,基于 Kotlin 编写,可以用于开发跨平台的 Android,iOS 和 ma…

张小明 2025/12/29 8:17:39 网站建设

广州做网站费用莞城东莞网站建设

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容: 开发一个类似Logitech Connection Utility的跨设备连接管理工具。需要实现以下功能:1)自动检测附近的Logitech蓝牙设备;2)提供简洁的配对界面;3)…

张小明 2025/12/26 12:18:30 网站建设

ftp上传wordpress网站要多久手机网站字体大小规范

文章目录FrameQueue 使用环形缓冲区的原因背景需求环形缓冲区优势FrameQueue vs 普通队列:核心差异keep_last 机制详解设计目的核心字段含义关键函数:frame_queue_peek()关键函数:frame_queue_next()运行示例(视频队列&#xff0c…

张小明 2025/12/26 12:17:56 网站建设