项目开发中的一些注意事项以及技巧总结 基于Repository模式设计项目架构—你可以参考的项目架构设计 Asp.Net Core中使用RSA加密 EF Core中的多对多映射如何实现? asp.net core下的如何给网站做安全设置 获取服务端https证书 Js异常捕获
项目开发中的一些注意事项以及技巧总结
1、jquery采用ajax向后端请求时,MVC框架并不能返回View的数据,也就是一般我们使用View()、PartialView()等,只能返回json以及content等,但是一般我们在开发的时候也是使用json返回的,此时如果需要渲染界面或者是加载局部视图,我们可以在ajax的success的事件中使用$.html()来渲染后台给前端传的View()数据。一开始我遇到这个问题的时候还很纳闷,为什么ajax给后端穿了POST之后,不能加载局部页面,后来一想,是不是因为ajax是异步请求的原因,于是我把ajax的同步开关打开了,同时将后台传输的视图数据直接使用$html()就渲染到了前端页面。具体请参考:https://blog.csdn.net/m0_37302219/article/details/78272081
2 、后端MVC架构,一般前端都是使用Razor视图,使用@来加载后台传过来的数据比如ViewData,以及ViewBag等。此时,我建议在后端的C#中,我们给ViewBag赋值了之后,在前端的cshtml页面中这么做:
@{
List<T> xxx = ViewBag.xxx;
T xxx = ViewBag.xxx;
}
然后直接使用显式类型的变量来做处理。
3、EF Core中,尤其要注意多对多的关联属性的使用。如果使用不当就会加载不出来数据,直接会出一个null值,在这里请参考
https://blog.oneunicorn.com/2017/09/25/many-to-many-relationships-in-ef-core-2-0-part-1-the-basics/
认真的跟着这个博客做一遍就可以理解了。
4、EF Core中,当我们使用code First建模方式生成数据库时,如果生成数据库有问题了(当然一般是没有问题的,但是我就遇到了,可能也是我操作不当)我强烈建议,不要删除这个生成有问题的数据库,千万不要觉得删除了之后,可以再生成一遍,会出问题的。具体请看
http://www.cjjjs.com/paper/lkkj/2018711212518513.html
5、EF Core下一对多的关联中,需要注意(我不怎么用过EF,也不知道在EF中是不是很正常,在这里仅仅说EF Core,可能两者在我要说的这点上是一致的)。我们以官方为例:https://docs.microsoft.com/en-us/ef/core/get-started/aspnetcore/existing-db
一个博客(Blog)对应多个文章(Post),一篇文章对应一个博客(Blog)。此时,当我们使用上下文来获取数据库数据时,代码如下:
List<Blog> Blogs = _context.Blogs.ToList();
List<Post> Posts = _context.Posts.ToList(); // 如果不写这句代码,不从数据库里面加载处理关联属性Post的数据,那么Blogs里面的Post关联属性也将会是null值,这点是要特别注意的,只有写了这句代码,Blogs类型的关联属性Post才能有数据。
6、项目中一定要设计好数据库,一般来讲如果有级联关系的,就设置为两个表(这里的级联关系我是这么定义的:假设一个类别下有多条数据,这就是一个级联关系,就像是一个省份下面有多个城市)。在实体方面,我们可以认为是一对多关系,如果是一对多关系,我们就建两个表。设计好了数据表,对我们的开发有着莫大的好处,有时候多加一个字段和少一个字段完全不一样。
7、建议在列表数据中使用ForEach来遍历,也就是一般的List<T>变量,使用List<T>.ForEach来遍历数据处理逻辑
基于Repository模式设计项目架构—你可以参考的项目架构设计
关于Repository模式,直接百度查就可以了,其来源是《企业应用架构模式》。
我们新建一个Infrastructure文件夹,这里就是基础设施部分,EF Core的上下文类以及Repository层都放在这里面。
新建一个IReposotory的接口,其内容就是封装了基本的CRUD:

- public interface IRepository<TEntity> where TEntity : class
- {
- ///获取当前实体的查询数据集
- IQueryable<TEntity> Entities{get;}
- ///获取当前实体的数据集
- DbSet<TEntity> DbEntities{get;}
- /// <summary>
- /// Gets all objects from database
- /// </summary>
- /// <returns></returns>
- IQueryable<TEntity> All();
- /// <summary>
- /// Gets objects from database by filter.
- /// </summary>
- /// <param name="predicate">Specified a filter</param>
- /// <returns></returns>
- IQueryable<TEntity> Filter(Expression<Func<TEntity, bool>> predicate);
- /// <summary>
- /// Gets objects from database with filting and paging.
- /// </summary>
- /// <param name="filter">Specified a filter</param>
- /// <param name="total">Returns the total records count of the filter.</param>
- /// <param name="index">Specified the page index.</param>
- /// <param name="size">Specified the page size</param>
- /// <returns></returns>
- IQueryable<TEntity> Filter(Expression<Func<TEntity, bool>> filter, out int total, int index = 0, int size = 50);
- /// <summary>
- /// Gets the object(s) is exists in database by specified filter.
- /// </summary>
- /// <param name="predicate">Specified the filter expression</param>
- /// <returns></returns>
- bool Contains(Expression<Func<TEntity, bool>> predicate);
- /// <summary>
- /// Find object by keys.
- /// </summary>
- /// <param name="keys">Specified the search keys.</param>
- /// <returns></returns>
- TEntity Find(params object[] keys);
- /// <summary>
- /// Find object by specified expression.
- /// </summary>
- /// <param name="predicate"></param>
- /// <returns></returns>
- TEntity Find(Expression<Func<TEntity, bool>> predicate);
- /// <summary>
- /// Create a new object to database.
- /// </summary>
- /// <param name="t">Specified a new object to create.</param>
- /// <returns></returns>
- int Create(TEntity t);
- /// <summary>
- /// Delete the object from database.
- /// </summary>
- /// <param name="t">Specified a existing object to delete.</param>
- void Delete(TEntity t);
- /// <summary>
- /// Delete objects from database by specified filter expression.
- /// </summary>
- /// <param name="predicate"></param>
- /// <returns></returns>
- int Delete(Expression<Func<TEntity, bool>> predicate);
- /// <summary>
- /// Update object changes and save to database.
- /// </summary>
- /// <param name="t">Specified the object to save.</param>
- /// <returns></returns>
- int Update(TEntity t);
- /// <summary>
- /// Select Single Item by specified expression.
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="expression"></param>
- /// <returns></returns>
- TEntity FirstOrDefault(Expression<Func<TEntity, bool>> expression);
- }

创建一个基类,用来实现IRepository接口,同时作其余的Repository的基类

- public class BaseRepository<TEntity> : IRepository<TEntity> where TEntity : class
- {
- protected readonly DbContext Context;
- public BaseRepository(DbContext context)
- {
- Context = context;
- }
- /// 获取当前实体的查询数据集
- public IQueryable<TEntity> Entities
- {
- get { return Context.Set<TEntity>().AsQueryable(); }
- }
- /// 获取当前实体
- public IQueryable<TEntity> Entities
- {
- get { return Context.Set<TEntity>(); }
- }
- public TEntity FirstOrDefault(Expression<Func<TEntity, bool>> expression)
- {
- return All().FirstOrDefault(expression);
- }
- public IQueryable<TEntity> All()
- {
- return Context.Set<TEntity>().AsQueryable();
- }
- public virtual IQueryable<TEntity> Filter(Expression<Func<TEntity, bool>> predicate)
- {
- return Context.Set<TEntity>().Where<TEntity>(predicate).AsQueryable<TEntity>();
- }
- public virtual IQueryable<TEntity> Filter(Expression<Func<TEntity, bool>> filter, out int total, int index = 0,
- int size = 50)
- {
- var skipCount = index * size;
- var resetSet = filter != null
- ? Context.Set<TEntity>().Where<TEntity>(filter).AsQueryable()
- : Context.Set<TEntity>().AsQueryable();
- resetSet = skipCount == 0 ? resetSet.Take(size) : resetSet.Skip(skipCount).Take(size);
- total = resetSet.Count();
- return resetSet.AsQueryable();
- }
- public virtual int Create(TEntity TObject)
- {
- Entities.Add(TObject);
- Context.SaveChanges();
- }
- public virtual int Delete(TEntity TObject)
- {
- Entities.Remove(TObject);.
- Context.SaveChanges();
- }
- public virtual void Update(TEntity TObject)
- {
- try
- {
- var entry = Context.Entry(TObject);
- Context.Set<TEntity>().Attach(TObject);
- entry.State = EntityState.Modified;
- }
- catch (OptimisticConcurrencyException ex)
- {
- throw ex;
- }
- }
- public virtual int Delete(Expression<Func<TEntity, bool>> predicate)
- {
- var objects = Filter(predicate);
- foreach (var obj in objects)
- Context.Set<TEntity>().Remove(obj);
- return Context.SaveChanges();
- }
- public bool Contains(Expression<Func<TEntity, bool>> predicate)
- {
- return Context.Set<TEntity>().Any(predicate);
- }
- public virtual TEntity Find(params object[] keys)
- {
- return Context.Set<TEntity>().Find(keys);
- }
- public virtual TEntity Find(Expression<Func<TEntity, bool>> predicate)
- {
- return Context.Set<TEntity>().FirstOrDefault<TEntity>(predicate);
- }
- }

新建一个实体类的接口:
- public interface IStudentRepository : IRepository<Student>
- {
- int AddStudent(Student student);
- }
然后我们创建一个实体类的Repository:

- public class StudentRepository : BaseRepository<Student>, IStudentRepository
- {
- private readonly SchoolContext _context;
- public StudentRepository(SchoolContext context)
- : base(context)
- {
- _context = context;
- }
- int AddStudent(Student student)
- {
- _context.Create(student);
- }
- }

在这里就已经做好了我们要做的了。接下来的就是注入依赖、在控制器里面的使用了。
我们完全可以自己来定制自己的Repository模式下的项目。其实整个的架构没有什么,我们只是将所有的CRUD操作封装到了IRepository接口里面,然后在BaseRepository中实现了一遍,而且如果你细心的话,你会发现IRepository里面的CRUD操作都是基于已有的扩展方法里面的,就是linq扩展方法的Add等源码,同时我们在BaseRepository类中,提供了DbSet<TEntity>属性以及查询数据集IQueryable<DbSet<TEntity>>,这也是有必要的,可以省却我们很多不必要的代码,因为我们所有的CRUD都是基于这两个的。然后我们基于BaseRepository来实现实体类的Repository,同时继承按需增加的IEntityRepository接口。但是在这里要注意,我们将DbContext的子类都放在了Infrastructure文件夹里面,是因为,一般我们继承自DbContext的子类都是操作数据库的中间类,属于基础设施一块,所以将其放在Infrastructure文件夹比较合适。
参考资料:
MVC实用架构设计(三)——EF-Code First(1):Repository,UnitOfWork,DbContext
分享基于Entity Framework的Repository模式设计(附源码)
《ASP.NET MVC框架揭秘》源码中的示例项目源码 S1402
EF Core中的多对多映射如何实现?
EF 6.X中的多对多映射是直接使用HasMany-HasMany来做的。但是到了EF Core中,不再直接支持这种方式了,可以是可以使用,但是不推荐,具体使用可以参考《你必须掌握的EntityFramework 6.X与Core 2.0》一文。在这里我就详细的说下如何在EF core下实现。
首先就是实体类的建立:

- public class Post
- {
- public int PostId { get; set; }
- public string Title { get; set; }
- public ICollection<PostTag> PostTags { get; } = new List<PostTag>();
- }
- public class Tag
- {
- public int TagId { get; set; }
- public string Text { get; set; }
- public ICollection<PostTag> PostTags { get; } = new List<PostTag>();
- }
- public class PostTag
- {
- public int PostId { get; set; }
- public Post Post { get; set; }
- public int TagId { get; set; }
- public Tag Tag { get; set; }
- }

接下来就是映射了。派生自DbContext的上下文类:

- public class MyContext : DbContext
- {
- public DbSet<Post> Posts { get; set; }
- public DbSet<Tag> Tags { get; set; }
- protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
- => optionsBuilder.UseSqlServer(
- @"Server=(localdb)\mssqllocaldb;Database=Test;ConnectRetryCount=0");
- protected override void OnModelCreating(ModelBuilder modelBuilder)
- {
- modelBuilder.Entity<PostTag>().ToTable("PostTags");
- modelBuilder.Entity<PostTag>()
- .HasKey(t => new { t.PostId, t.TagId });
- }
- }

这样就完成了我们的多对多映射了。我们只是通过多建立了一个表,将两个实体类的Id作为联合主键。
在Identity框架中,如果你细心点,你会发现有个userroles表,这个表是就是用来做Users表和Roles表的映射的。那么接下来我们只要新建一个实体类,随后在上下文类中映射到表:
- modelBuilder.Entity<UserRoles>.ToTable("userroles");
这样就可以了。然后我们就可以很方便的给用户添加角色了。
参考链接:https://blog.oneunicorn.com/2017/09/25/many-to-many-relationships-in-ef-core-2-0-part-1-the-basics/
asp.net core下的如何给网站做安全设置
首先,我们来看下stack overflow网站的请求头文件:
可以看到一些我们熟悉或是陌生的HTTP头部文件字段。
在这里我们在对HTTP输入流的头部文件中,做一些基本的防护。首先要明确,既然我们是对HTTP头部做处理,那么就需要在Startup.cs类的
Configuration方法中做处理,因为这里就是处理HTTP输入流的。
首先做一些基本的处理,比如中间件和基本的类:
1
2
3
4
5
6
7
8
|
public class SecurityHeadersPolicy { public IDictionary< string , string > SetHeaders { get ; } = new Dictionary< string , string >(); public ISet< string > RemoveHeaders { get ; } = new HashSet< string >(); } |
这里的头部信息是我们定义好的,用来增加或是删除头部信息,然后就是我们的中间件:

- public class SecurityHeadersMiddleware
- {
- private readonly RequestDelegate _next;
- private readonly SecurityHeadersPolicy _policy;
- public SecurityHeadersMiddleware(RequestDelegate next, SecurityHeadersPolicy policy)
- {
- _next = next;
- _policy = policy;
- }
- public async Task Invoke(HttpContext context)
- {
- IHeaderDictionary headers = context.Response.Headers;
- foreach (var headerValuePair in _policy.SetHeaders)
- {
- headers[headerValuePair.Key] = headerValuePair.Value;
- }
- foreach (var header in _policy.RemoveHeaders)
- {
- headers.Remove(header);
- }
- await _next(context);
- }
- }

基于IApplicationBuilder接口做一个中间件的扩展方法:

- public static class MiddlewareExtensions
- {
- public static IApplicationBuilder UseSecurityHeadersMiddleware(this IApplicationBuilder app, SecurityHeadersBuilder builder)
- {
- SecurityHeaderPolicy policy = builder.Build();
- return app.UseMiddleware<SecurityHeadersMiddleware>(policy);
- }
- }

封装好相关的安全类:

- public class SecurityHeadersBuilder
- {
- private readonly SecurityHeadersPolicy _policy = new SecurityHeadersPolicy();
- public SecurityHeadersBuilder AddDefaultSecurePolicy()
- {
- AddFrameOptionsDeny();
- AddXssProtectionBlock();
- AddContentTypeOptionsNoSniff();
- AddStrictTransportSecurityMaxAge();
- RemoveServerHeader();
- return this;
- }
- public SecurityHeadersBuilder AddFrameOptionsDeny()
- {
- _policy.SetHeaders[FrameOptionsConstants.Header] = FrameOptionsConstants.Deny;
- return this;
- }
- public SecurityHeadersBuilder AddFrameOptionsSameOrigin()
- {
- _policy.SetHeaders[FrameOptionsConstants.Header] = FrameOptionsConstants.SameOrigin;
- return this;
- }
- public SecurityHeadersBuilder AddFrameOptionsSameOrigin(string uri)
- {
- _policy.SetHeaders[FrameOptionsConstants.Header] = string.Format(FrameOptionsConstants.AllowFromUri, uri);
- return this;
- }
- public SecurityHeadersBuilder RemoveServerHeader()
- {
- _policy.RemoveHeaders.Add(ServerConstants.Header);
- return this;
- }
- public SecurityHeadersBuilder AddCustomHeader(string header, string value)
- {
- _policy.SetHeaders[header] = value;
- return this;
- }
- public SecurityHeadersBuilder RemoveHeader(string header)
- {
- _policy.RemoveHeaders.Add(header);
- return this;
- }
- public SecurityHeadersPolicy Build()
- {
- return _policy;
- }
- }

最后注入到HTTP的输入流中:
- app.UseSecurityHeadersMiddleware(new SecurityHeadersBuilder()
- .AddDefaultSecurePolicy()
- );
然后我们浏览一下网页,就可以在HTTP的头部信息中看到:

- HTTP/1.1 200 OK
- Content-Type: text/html; charset=utf-8
- X-Frame-Options: DENY
- X-XSS-Protection: 1; mode=block
- X-Content-Type-Options: nosniff
- Strict-Transport-Security: max-age=31536000
- X-Powered-By: ASP.NET

还有一个就是CSRF的防护,如果之前你用过ASP.NET MVC,在最基本的MVC模板中,可能你会留意到已有的cshtml页面中的form表单有这么一句:
- @Html.AntiForgeryToken()
这就是微软在MVC框架中为我们提供的防护CSRF的方法。我们在表单中直接使用上面那句代码就可以了,然后在表单提交的Action方法中:
- [ValidateAntiForgeryToken]
- [HttpPost]
- public IActionResult AntiForm(string message)
- {
- return Content(message);
- }
使用[ValidateAntiForgeryToken]属性,来验证CSRF。
参考链接:
How to add security headers in ASP.NET Core using custom middleware(如何使用自定义中间件在ASP.NET Core中添加安全标头)
代码地址:
https://github.com/RyanOvO/aspnetcore-fileup-demo
获取服务端https证书
最近开发一个需求,涉及获取服务端https证书。一般进行https调用我们都不太关心底层细节,直接使用WebClient或者HttpWebRequest来发送请求,这两种方法都无法获取证书信息,需要用到ServicePoint,这个类用于提供HTTP连接的管理。
写个Demo,拿新浪首页试一下:

- using System;
- using System.Net;
- using System.Security.Cryptography.X509Certificates;
- namespace GetServerCertificateDemo
- {
- class Program
- {
- static void Main(string[] args)
- {
- //用WebClient访问新浪首页
- var http = new WebClient();
- var uri = new Uri("https://www.sina.com.cn");
- http.DownloadString(uri);
- //通过Uri获取ServicePoint
- var servicePoint = ServicePointManager.FindServicePoint(uri);
- //取服务端证书,X509Certificate格式,转一下
- var serverCert = new X509Certificate2(servicePoint.Certificate);
- Console.WriteLine("颁发给:{0}", serverCert.Subject);
- Console.WriteLine("颁发者:{0}", serverCert.Issuer);
- Console.WriteLine("序列号:{0}", serverCert.SerialNumber);
- Console.WriteLine("指 纹:{0}", serverCert.Thumbprint);
- Console.WriteLine("起 始:{0}", serverCert.NotBefore);
- Console.WriteLine("过 期:{0}", serverCert.NotAfter);
- }
- }
- }

运行看效果:
上半部分是程序运行结果,下面是用Firefox查看的服务端证书信息,各项信息都能对应上。如果程序中涉及多个不同服务器的访问也没关系,关键在于根据Uri获取ServicePoint,然后取到的证书就是此服务器的了。
Js异常捕获

- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="UTF-8">
- <title></title>
- </head>
- <body>
- <script>
- function demo(){
- try{
- alert(str);
- }catch(e){
- alert(e);
- }
- }
- demo();
- </script>
- <form>
- <input id="txt" type="text"/>
- <input id="btn" type="button" onclick="demo1()" value="按钮" />
- </form>
- <script>
- function demo1(){
- try{
- var e=document.getElementById("txt").value;
- if(e==""){
- throw "请输入";
- }
- }catch(e){
- alert(e);
- }
- }
- </script>
- </body>
- </html>

js事件
onLoad 网页加载事件
onUnload 关闭网页事件
反射:获取Class对象的三种方式
数据库_mysql多表操作
数据库_mysql多表操作
多表操作
实际开发中,一个项目通常需要很多张表才能完成。例如:一个商城项目就需要分类表(category)、商品表(products)、订单表(orders)等多张表。且这些表的数据之间存在一定的关系。
1.1 表与表之间的关系
l 一对多关系:
n 常见实例:客户和订单,分类和商品,部门和员工.
n 一对多建表原则:在从表(多方)创建一个字段,字段作为外键指向主表(一方)的主键.
l 多对多关系:
n 常见实例:学生和课程、用户和角色
n 多对多关系建表原则:需要创建第三张表,中间表中至少两个字段,这两个字段分别作为外键指向各自一方的主键.
l 一对一关系:(了解)
n 在实际的开发中应用不多.因为一对一可以创建成一张表.
n 两种建表原则:
u 外键唯一:主表的主键和从表的外键(唯一),形成主外键关系,外键唯一unique。
u 外键是主键:主表的主键和从表的主键,形成主外键关系。
1.2 外键约束
现在我们有两张表“分类表”和“商品表”,为了表明商品属于哪个分类,通常情况下,我们将在商品表上添加一列,用于存放分类cid的信息,此列称为:外键
此时“分类表category”称为:主表,“cid”我们称为主键。“商品表products”称为:从表,category_id称为外键。我们通过主表的主键和从表的外键来描述主外键关系,呈现就是一对多关系。
外键特点:
u 从表外键的值是对主表主键的引用。
u 从表外键类型,必须与主表主键类型一致。
l 声明外键约束
语法:alter table 从表 add [constraint] [外键名称] foreign key (从表外键字段名) references 主表 (主表的主键);
[外键名称]用于删除外键约束的,一般建议“_fk”结尾
altertable 从表 drop foreignkey 外键名称
l 使用外键目的:
n 保证数据完整性
1.3 一对多操作
1.3.1 分析
category分类表,为一方,也就是主表,必须提供主键cid
products商品表,为多方,也就是从表,必须提供外键category_id
1.3.2 实现:分类和商品
###创建分类表
create table category(
cidvarchar(32) PRIMARY KEY ,
cnamevarchar(100) #分类名称
);
# 商品表
CREATE TABLE `products` (
`pid`varchar(32) PRIMARY KEY ,
`name`VARCHAR(40) ,
`price`DOUBLE
);
#添加外键字段
alter table products add column category_id varchar(32);
#添加约束
alter table products add constraint product_fkforeign key (category_id) references category (cid);
1.3.3 操作
#1 向分类表中添加数据
INSERT INTO category (cid ,cname) VALUES('c001','服装');
#2 向商品表添加普通数据,没有外键数据,默认为null
INSERT INTO products (pid,pname) VALUES('p001','商品名称');
#3 向商品表添加普通数据,含有外键信息(数据存放在)
INSERT INTO products (pid ,pname ,category_id)VALUES('p002','商品名称2','c001');
#4 向商品表添加普通数据,含有外键信息(数据不存在) -- 不能异常
INSERT INTO products (pid ,pname ,category_id)VALUES('p003','商品名称2','c999');
#5 删除指定分类(分类被商品使用) -- 执行异常
DELETE FROM category WHERE cid = 'c001';
1.4 多对多
1.4.1 分析
商品和订单多对多关系,将拆分成两个一对多。
products商品表,为其中一个一对多的主表,需要提供主键pid
orders 订单表,为另一个一对多的主表,需要提供主键oid
orderitem中间表,为另外添加的第三张表,需要提供两个外键oid和pid
1.4.2 实现:订单和商品
### 商品表[已存在]
### 订单表
create table `orders`(
`oid`varchar(32) PRIMARY KEY ,
`totalprice` double #总计
);
### 订单项表
create table orderitem(
oidvarchar(50),-- 订单id
pidvarchar(50)-- 商品id
);
###---- 订单表和订单项表的主外键关系
alter table `orderitem` add constraintorderitem_orders_fk foreign key (oid) references orders(oid);
###---- 商品表和订单项表的主外键关系
alter table `orderitem` add constraintorderitem_product_fk foreign key (pid) references products(pid);
### 联合主键(可省略)
alter table `orderitem` add primary key (oid,pid);
1.4.3 操作
#1 向商品表中添加数据
INSERT INTO products (pid,pname) VALUES('p003','商品名称');
#2 向订单表中添加数据
INSERT INTO orders (oid ,totalprice)VALUES('x001','998');
INSERT INTO orders (oid ,totalprice)VALUES('x002','100');
#3向中间表添加数据(数据存在)
INSERT INTO orderitem(pid,oid)VALUES('p001','x001');
INSERT INTO orderitem(pid,oid)VALUES('p001','x002');
INSERT INTO orderitem(pid,oid)VALUES('p002','x002');
#4删除中间表的数据
DELETE FROM orderitem WHERE pid='p002' AND oid ='x002';
#5向中间表添加数据(数据不存在) -- 执行异常
INSERT INTO orderitem(pid,oid)VALUES('p002','x003');
#6删除商品表的数据 -- 执行异常
DELETE FROM products WHERE pid = 'p001';
项目开发中的一些注意事项以及技巧总结 基于Repository模式设计项目架构—你可以参考的项目架构设计 Asp.Net Core中使用RSA加密 EF Core中的多对多映射如何实现? asp.net core下的如何给网站做安全设置 获取服务端https证书 Js异常捕获的更多相关文章
- 基于Repository模式设计项目架构—你可以参考的项目架构设计
关于Repository模式,直接百度查就可以了,其来源是<企业应用架构模式>.我们新建一个Infrastructure文件夹,这里就是基础设施部分,EF Core的上下文类以及Repos ...
- asp.net core下的如何给网站做安全设置
首先,我们来看下stack overflow网站的请求头文件: 可以看到一些我们熟悉或是陌生的HTTP头部文件字段.在这里我们在对HTTP输入流的头部文件中,做一些基本的防护.首先要明确,既然我们是对 ...
- asp.net获取服务端和客户端信息
asp.net获取服务端和客户端信息 获取服务器名:Page.Server.ManchineName获取用户信息:Page.User 获取客户端电脑名:Page.Request.UserHostNam ...
- 使用RSA加密在Python中逆向shell
i春秋翻译小组-Neo(李皓伟) 使用RSA加密在Python中逆向shell 这是一个关于使用RSA加密编程逆向shell的python教程. 我想提一下,这篇文章更多的是关于理解shell中涉及的 ...
- 总结项目开发中用到的一些css\html技巧
这篇就是用来总结记录的,会长期更新. 1,半透明背景效果(#ffffff颜色的半透明背景): font-style: italic;">#ffffff; filter:alpha(op ...
- php开发中怎么获取服务端MAC地址?
MAC(Media Access Control或者Medium Access Control)地址,意译为媒体访问控制,或称为物理地址.硬件地址,用来定义网络设备的位置.在php中如何获取MAC(M ...
- 基于ASP.NET WPF技术及MVP模式实战太平人寿客户管理项目开发(Repository模式)
亲爱的网友,我这里有套课程想和大家分享,假设对这个课程有兴趣的.能够加我的QQ2059055336和我联系. 课程背景 本课程是教授使用WPF.ADO.NET.MVVM技术来实现太平人寿保险有限公司 ...
- 使用Jquery+EasyUI 进行框架项目开发案例讲解之五 模块(菜单)管理源码分享
http://www.cnblogs.com/huyong/p/3454012.html 使用Jquery+EasyUI 进行框架项目开发案例讲解之五 模块(菜单)管理源码分享 在上四篇文章 ...
- 使用Jquery+EasyUI 进行框架项目开发案例讲解之四 组织机构管理源码分享
http://www.cnblogs.com/huyong/p/3404647.html 在上三篇文章 <使用Jquery+EasyUI进行框架项目开发案例讲解之一---员工管理源码分享> ...
随机推荐
- Linux Oracle DB log 清理
sid_list=`/bin/ps -ef |/bin/grep smon |/bin/grep -v grep | /bin/cut -f3 -d_` host_name=`hostname` cd ...
- C#发送POST,GET,DELETE请求API,并接受返回值
发送POST请求 /// <summary> /// API发送POST请求 /// </summary> /// <param name="url" ...
- AC日记——Sliding Window poj 2823
2823 思路: 单调队列: 以前遇到都是用线段树水过: 现在为了优化dp不得不学习单调队列了: 代码: #include <cstdio> #include <cstring> ...
- HDU 6299.Balanced Sequence-贪心、前缀和排序 (2018 Multi-University Training Contest 1 1002)
HDU6299.Balanced Sequence 这个题就是将括号处理一下,先把串里能匹配上的先计数去掉,然后统计左半边括号的前缀和以及右半边括号的前缀和,然后结构体排序,然后遍历一遍,贪心策略走一 ...
- (1)C#工具箱-公共控件1
公共控件 InitializeComponent() 先说下InitializeComponent()这个方法,它在form1.cs里调用这个方法对控件进行初始化,控件的方法要在这个方法之后,否则会因 ...
- 基于django rest framework的mock server实践
网上找了一下mock server的实现,发现python的基本都是基于flask来实现的,因最近在学django,就尝试用drf实现了下: A brief introduction of sui_m ...
- HDU 3237 Tree(树链剖分)(线段树区间取反,最大值)
Tree Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 9123 Accepted: 2411 Description ...
- javascript与java的不同之处
javascript与java的不同之处 虽然很像,但不是一种语言. 二者的区别体现在: 首先,它们是两个公司开发的不同的两个产品,Java是SUN公司推出的新一代面向对象的程序设计语言,特别适合 ...
- Visual Studio Package扩展——vsct文件简介
首先我们使用向导生成一个package的扩展,里面就会发现一个vsct文件.vsct文件的全称是Visual Studio Command Table,它其实就是一个xml文件,通过一定的规则来描述v ...
- 利用osql/ocmd批处理批量执行sql文件
原文:利用osql/ocmd批处理批量执行sql文件 上周在测试环境建了几十张表,保存了.sql文件,准备在正式环境重建的时候懒得一个个打开建了,做一在网上搜寻了一下,果然有简单点的方法. 利用osq ...