Upgrading to .NET Core 2.0 Preview

1 更新 依赖的类库 改为 标准库

2 web app  更改 csproj 文件---升级版本

<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0-preview1-final" />
<PackageReference Include="Microsoft.AspNetCore" Version="1.0.4" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.0.3" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="1.0.2" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="1.0.2" />
<PackageReference Include="Microsoft.VisualStudio.Web.BrowserLink" Version="1.0.1" />
</ItemGroup>

其他变动参考下面的文章,细节。

(visual studio code 编辑器出中文语言包了!?!?!?!??)

参考:https://weblog.west-wind.com/posts/2017/May/15/Upgrading-to-NET-Core-20-Preview

Over the weekend I spent a bit of time updating my AlbumViewer Sample Angular and ASP.NET Core Application to .NET Core 2.0. The good news is that for the most part this is another relatively smooth update, with some nice payoffs, but also a couple of pain points.

Album Viewer

Just to set the stage for those of you that haven't heard me blabber about my sample project before: I have an AlbumViewer sample application I've been carrying forward through all the versions of .NET Core (and Angular as well) from earlier previews to today. The album viewer is a smallish application of a .NET Core ASP.NET API to an Angular (4) front end application that's made up of four separate projects:

  • ASP.NET Core Web app that handles the Web API backend
  • .NET business object project that holds Repository and EF access code
  • .NET utility project with a few helpers
  • Angular front end Web Site Project (discussed in detail in my previous update post)

Although the project is relatively small that could easily live in a single project, I broke out functionality into multiple projects to make it a little more realistic and exercise the the inter-project dependencies and different behaviors of Web and separate class library projects under .NET Core.

You can find the project on Github at:

  • AlbumViewer Sample Project on GitHub

and the running application (currently on 1.1 still):

  • AlbumViewer Online Sample
  • Updating my AlbumViewer Sample to .NET Core 1.1 and Angular 4

The conversion for .NET Core 2 discussed in this post currently lives on a side GitHub branch NET_CORE_2_MIGRATION for the time being until there's more stable tooling available. As with the 1.1 upgrade, the .NET Core 2 features require the latest version of Visual Studio Preview in order to work. So the Master branch will continue to stay on version 1.1 of .NET Core that can run comfortably on current production tools and runtimes.

Getting started with .NET Core 2.0

In order to use the .NET Core 2.0 features you'll need to install a couple of things:

  • .NET Core 2.0 SDK
  • Visual Studio 2017 v15.3 Preview 1

Visual Studio is optional if you want to work from the command line or you're not running on Windows. The SDK is the key piece you need.

Important!

Even if you install the Visual Studio Preview, you'll still need to install the .NET Core 2 SDK as the Preview 1 release of Visual Studio does not install it. This will change in the future, but for now - install it explicitly.

Upgrading to .NET Core 2.0 and .NET Standard 2.0 - mostly easy

So, the good news is that 99% of the upgrade to .NET Core was very easy and quick and boiled down to a few very simple steps:

  • Changing the target of the Class Library projects to .NET Standard 2.0
  • Changing the target of the Web API project to .NET Core App 2.0
  • In the Web Project adding a reference to Microsoft.AspNetCore.All
  • In the Web Project removing most other ASP.NET related Nuget references

And that's it! Let's go over those.

Changing the Target Framework

I used Visual Studio to change the Build target of each of the 3 projects. The Class Libraries are set to target .NET Standard 2.0, while the Web app targets .NET Core 2.0.

Here's the setting to .NET Standard 2.0 in the class library projects:

 Figure 1 - Setting .NET Standard 2.0 in Visual Studio's Build Settings for the class library projects

Making this change causes the TargetFramework to be changed to netstandard2.0 in the project's .csproj file.

If you're not using Visual Studio you can also make this change directly in the .csproj file:

<Project Sdk="Microsoft.NET.Sdk"><PropertyGroup> <!-- *** THIS ONE *** --> <TargetFramework>netstandard2.0</TargetFramework> ... </PropertyGroup> ... </Project> 

In the Web App the settings look slightly different - there you have to use netcoreapp2.0 for the TargetFramework.

 Figure 2 - Configuring .NET Core version in a Web Project

and here are the settings for the .csproj file:

<Project Sdk="Microsoft.NET.Sdk.Web"><PropertyGroup> <PropertyGroup> <!-- *** THIS ONE *** --> <TargetFramework>netcoreapp2.0</TargetFramework> <PreserveCompilationContext>true</PreserveCompilationContext> <AssemblyName>AlbumViewerNetCore</AssemblyName> <OutputType>Exe</OutputType> <PackageId>AlbumViewerNetCore</PackageId> <PackageTargetFallback>$(PackageTargetFallback);dotnet5.6;portable-net45+win8</PackageTargetFallback> </PropertyGroup> ... </Project> 

Right - the madness of versions, SDKs, and runtimes continues. netcoreapp2.0 is an a concrete .NET version reference - .NET Core 2.0 specifically, while netstandard2.0 is used for class libraries that build a library that conforms to the .NET Standard specification. So currently the ASP.NET startup project is marked with netcoreapp while class libraries generally will target netstandard. If you're confused by this madness - you're not alone and I'll have more to say and the reasons for this at the end of this post.

Replacing ASP.NET Packages the consolidated Microsoft.AspNetCore.All Meta Package

In ASP.NET Core 2.0 Microsoft is providing a bundled ASP.NET Core package that includes most of the ASP.NET feature packages in a single reference bundle. This package is actually a placeholder that triggers import of the required child packages as needed when the application is compiled.

Here's what this looks like when you add Microsoft.AspNetCore.All to your project:

<Project Sdk="Microsoft.NET.Sdk.Web">...<ItemGroup> <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0-preview1-final" /> <PackageReference Include="Serilog.Extensions.Logging" Version="1.4.0" /> <PackageReference Include="Serilog.Sinks.RollingFile" Version="3.3.0" /> </ItemGroup> <ItemGroup> <ProjectReference Include="..\AlbumViewerBusiness\AlbumViewerBusiness.csproj" /> </ItemGroup> <!-- *** Old References are Removed *** <ItemGroup> <PackageReference Include="Microsoft.AspNetCore.Diagnostics" Version="1.1.1" /> <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.1.2" /> <PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="1.1.1" /> <PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="1.1.1" /> <PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="1.1.1" /> <PackageReference Include="Microsoft.AspNetCore.Cors" Version="1.1.1" /> <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="1.1.1" /> <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="1.1.1" /> <PackageReference Include="Microsoft.Extensions.Logging" Version="1.1.1" /> <PackageReference Include="Microsoft.Extensions.Logging.Filter" Version="1.1.1" /> <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="1.1.1" /> <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="1.1.1" /> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="1.1.0" /> <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="1.1.0" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="1.1.0" /> <PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="1.1.0" /> <PackageReference Include="Microsoft.AspNetCore.Authentication.Cookies" Version="1.1.1" /> <PackageReference Include="Microsoft.Extensions.Configuration.CommandLine" Version="1.1.1" /> <PackageReference Include="Serilog.Extensions.Logging" Version="1.4.0" /> <PackageReference Include="Serilog.Sinks.RollingFile" Version="3.3.0" /> </ItemGroup>--> ... 

Notice the large commented block: That's all the stuff I removed in favor of the Microsoft.AspNetCore.All meta package. There are no other Microsoft packages referenced directly in the Reference section - everything needed is coming in through the meta package.

You end up with a much cleaner looking project that looks a lot more sensible, with the stuff you are actually working with, rather than seeing a mess of plumbing dependencies that have nothing to do with the application code you're writing.

This is an overdue improvement. Nice!

You can see how this makes the project look much cleaner. Check out the project references in this screen shot from Visual Studio:

Figure 3 - A three project Web app with its dependencies highlighted

This is much cleaner than what we had especially prior to the move to .csproj and 1.1 and now even more so in 2.0. This is starting to look a lot more like classic .NET projects where you see only the references your code is referencing, which is what it should be.

Making these changes took all of 5 minutes and I was able to get my project compiled except for 2 issues.

Authentication Changes

This almost made my application compile. Yeah, but it never just works, right? All of the above worked except one compilation error related to Authentication.

 Figure 4 - Authentication config has changed in ASP.NET Core 2.0 and has to be updated. This code that worked in 1.1 in Configure() no longer works.

The Authentication provider in ASP.NET Core 2.0 has been refactored and the old way of configuration and accessing has been replaced by a slightly different configuration code path. The changes are relatively minor, but I got rather frustrated because there's no documentation yet and the stuff of course isn't discoverable in any way since it all comes in from DI.

In the AlbumViewer, I use very simple API endpoint based security. There's an account/login endpoint that validates a username and password and then sets an Auth Cookie with a ClaimsIdentity. As complex as the ASP.NET Identity system is, its saving grace is that you can still do simple things like this with little effort, effectively offloading the authorization to your own business logic and letting ASP.NET Core do the important part of encrypting the Claims based cookie and picking up the User Identity as part of the middleware processing. Doing this sort of thing requires very little code and is quite manageable.

Let's take a look at the old code and new code side by side. The logic of this code really doesn't change much at all, just the APIs called change a little.

Old Code (ASP.NET Core 1.1)

ConfigureServices() method

services.AddAuthentication();

Configure() method

 // Enable Cookie Auth with automatic user policy
app.UseCookieAuthentication(new CookieAuthenticationOptions()
{AutomaticAuthenticate = true,AutomaticChallenge = false,LoginPath = "/api/login" }); 

Login API Endpoint

[AllowAnonymous]
[HttpPost]
[Route("api/login")]
public async Task<bool> Login([FromBody] User loginUser) { var user = await accountRepo.AuthenticateAndLoadUser(loginUser.Username, loginUser.Password); if (user == null) throw new ApiException("Invalid Login Credentials", 401); var identity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme); identity.AddClaim(new Claim(ClaimTypes.Name, user.Username)) ; if (user.Fullname == null) user.Fullname = string.Empty; identity.AddClaim(new Claim("FullName", user.Fullname)); await HttpContext.Authentication.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(identity)); return true; } 

New Code (ASP.NET Core 2.0)

ConfigureServices() method

services.AddCookieAuthentication(o =>
{o.LoginPath = "/api/login";o.LogoutPath = "/api/logout";
});

Configure() method

app.UseAuthentication();

Login API Endpoint

[AllowAnonymous]
[HttpPost]
[Route("api/login")]
public async Task<bool> Login([FromBody] User loginUser) { var user = await accountRepo.AuthenticateAndLoadUser(loginUser.Username, loginUser.Password); if (user == null) throw new ApiException("Invalid Login Credentials", 401); var identity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme); identity.AddClaim(new Claim(ClaimTypes.Name, user.Username)) ; if (user.Fullname == null) user.Fullname = string.Empty; identity.AddClaim(new Claim("FullName", user.Fullname)); // *** NOTE: SignInAsync is now on the HttpContext instance! *** await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(identity)); return true; } 

As you can see, Microsoft decided to shuffle the deck chairs a little. The auth configuration has moved to ConfigureServices(). Options are now passed to the specific Authentication service declaration (AddCookieAuthentication()). If you're using a auth provider rather than Cookies like OpenID, Facebook, etc. there are methods for those specific configuration providers as extensions methods that have moved in the same way.

The Configure() method then simply attaches the authentication middleware using AddAuthentication() without further settings .

This makes a lot more sense. It's never sat right with me that some things are configured in the 'Configure()' method. It seems if you're going to use DI let all configuration happen at the ConfigureService() level and it looks like Microsoft is taking that approach to move configuration tasks into that common place. I suspect we'll see more of these types of refactorings in the future. Logging comes to mind which still has a bunch of settings set in Configure().

For the actual authentication implementation code there's only one very subtle change in the call to:

await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme,new ClaimsPrincipal(identity));

which changes to directly getting called on HttpContext object instead of the HttpContext.Authentication. Confusingly the HttpContext.Authentication instance still exists and even has a SignInAsync() method, but it no longer works correctly.

Visual Studio Tooling Pain - again

It looks like in Visual Studio 2017 and the .NET Core 2 preview the tooling once again has reverted to an unstable state. When first loading up the project, Visual Studio showed all sorts of errors in the code viewers and compiler errors, even though the code was compiling from the command line.

Check out this lovely screen shot I shared on Twitter on Friday:

Figure 4 - Visual Studio Tooling not resolving references

The terminal on the bottom is running the same application, while Visual Studio is flagging all sorts of reference errors and won't compile. Even compiling externally wouldn't help - only way to fix was to Close Solution, re-open Solution.

To get around this, I've been using Visual Studio Code and command line tooling lately because of the incessant pain that the Visual Studio is causing with .NET Core. However, when doing these migrations, it's certainly helpful to have Visual Studio automatically add framework and package references which is easier to do in the full IDE especially if you don't know what you're looking for.

.NET Standard 2.0 - Finally

With this release we finally get some .NET Core 2.0 bits that we can play with. One of the key reasons I've been excited about the .NET Core 2.0 update is support for .NET Standard 2.0 and the much expanded API it brings. .NET Standard 2.0 more than doubles the surface of the .NET Core 1.1 API and brings back a shitload of APIs that were missing and made it a lot more difficult than it should be to re-use full framework code in .NET Core.

I spent a bit of time over the weekend creating a few test .NET Core 2.0 projects and throwing some of my full framework assemblies at them. You can now easily add full framework assemblies to your .NET Core 2.0 projects and have a pretty good chance that the assembly will just work without major changes - assuming it doesn't use features that .NET Core doesn't provide. It turns out the delta between what works in full framework and .NET Core 2.0 got a lot smaller in .NET Core 2.0 and many common things just work.

Keep in mind that there are still quite a few features that are not supported in .NET Core. I ran afoul with a few data apis (DbProviderFactories and CreateDataAdapter for example) and most commonly the non-support of System.Configuration APIs which include .config file access and ConnectionStrings. Those particular features I have to work around in my libraries.

Also remember that failures won't bomb at compile time, but at runtime. This means you can use an assembly even if there are some features that don't work as long as you don't call into an execution path that accesses those.

For example, Westwind.Utilities has a boat load of general purpose helper functions. A very large percentage of that library will just work as is. The data apis, the string and file apis, most of the reflection tools and even the configuration bits once adjusted to not default to the .config provider actually worked. In fact in the AlbumViewer sample I could reference the full framework assembly now and replace the small subset project I created to provide the features I needed.

To me this has been the biggest reason to hold off with a .NET Core development because clearly the expanded API surface in .NET Core 2.0 will make it much easier to reuse existing code without any changes (if it's well factored code) or with some relatively minor re-configuration or code bracketing to avoid unsupported APIs.

Pick a Number, Any Number

Overall this framework update provides a relatively smooth upgrade path aside from a few breaking changes.

But one thing that is extremely frustrating is the proliferation of SDKs, Runtimes, Tools and all the different versions that they incorporate. Especially when those things end up not quite lining up because they are all in different stages of preview.

Let's see we have (with preview sub versions):

  • .NET Core 2.0
    The .NET Runtime Core version that runs the actual application. This can be 1.0, 1.1 or now 2.0. This is the concrete implementation that you run. This is really formalized by the netcoreapp2.0 setting in a startup project.

  • .NET Standard 2.0
    Is mainly used for class libraries where you can specify .NET Standard 2.0 as a target so that your assembly can be used in any .NET Standard compliant application. Think of it as creating an library that conforms to an interface/standard/specification. - netstandard2.0

  • .NET Core App 2.0
    Specifies a concrete version of the framework - .NET Core 2.0 in this case - that is to be run by an executable. ASP.NET 2.0 needs to use this due a problem with this preview, whereby ASP.NET couldn't bind to .NET Standard 2.0 as it uses some APIs that haven't been moved to Standard 2.0 yet. This will be fixed in future previews. This is also the reason that ASP.NET Core 2.0 currently can't run with the full framework runtime (which uses .NET Standard 2.0). If you're using .NET Core this has no real side effects, other than the different target name and again in the next Preview the Web will target .NET Standard and work with full framework again. - netcoreapp2.0

  • .NET Core SDK 2.0
    This is the SDK version that you use to build, run and publish your applications with - essentially everything surrounding the dotnet and the tooling required to make it work. Newer versions of this SDK support building apps of older versions back to 1.0 at this point. So if you install the newer SDK, you should be good to go. You can override the SDK explicitly by using global.json file that specifies an explicit SDK version. If not specified the highest version installed SDK is used.

Andrew Locke has a good post on the topics of runtimes and SDKs, but the mere fact we need to have blog posts trying to explain version numbers and how .NET Standard works in relation to the .NET runtime is a major failing of the platform IMHO.

That's a lot of different components to take in. As a developer I shouldn't have to care about most of these things. I should be able to pick a target (.NET Standard 2.0 or Net Core App) or multiples in the case of class libs, and the tooling should be able to figure out what I need to build an application that supports that target. And hopefully let me change those targets just as easily when new versions roll around.

Confucius say - Shut up and Dance!

To make things even more confusing the tooling does some crazy stuff in the latest version when it displays information about the SDK usage in a Visual Studio project:

Check out this ditty:


Figure 5 - .NET Standard 2.0 pointing at 1.1 platform packages. Okay dokey!

that seems to indicate I'm running version 1.1.0 of... something. When I first upgraded I kept thinking the upgrade didn't work even though my project had .NET Core 2.0 set for all projects.

Damien Edwards straightened me out on Twitter indicating that 1.1.0 has nothing to do with the .NET Standard version - it's simply one of the dependent packages. Ok fair enough, but why the heck is this showing at all? NetCorePlatforms? Packaging Tools? Why are these important when I don't even know what these are? It turns out that the current formatting in VS is missing the .NET Standard or .NET Core App designation on the NetStandard.Library node, which is an ordinary omission bug in this release but as to the other values that's a mystery...

It's not that .NET Core is really all that difficult - it really isn't. But when you see this salad of SDKs and versions plus the uhm... sub-par tooling experience when you first walk up to .NET Core I don't think the first experience is a positive one for the majority of developers.

Keeping out the stuff you don't need to see is key to that - it's fine that it's there to tinker with, but the base tooling should let developers focus on the stuff they need to work on and not the plumbing underneath.

Summary

While the tooling issues and version overload is annoying in a lot of ways, lets remember that this is a preview. I also think .NET Core is well worth some of the growing pains we're seeing. Once you're on your way building an application the process is not that different from what it used to be with full framework .NET that came before - especially now with .NET Core 2.0 and .NET Standard 2.0 providing a much richer baseline API that makes it much easier to use or adapt existing full framework code into .NET Core.

Hopefully the messaging around the various components will get a bit clearer and become more established so we don't have to run around with our heads cut off each time a new version comes out and we need to upgrade our projects.

Resources

  • AlbumViewer Sample on Github
  • ASP.NET Core Breaking Changes
this post created with Markdown Monster

Other Posts you might also like

  • Publishing and Running ASP.NET Core Applications with IIS
  • More on ASP.NET Core Running under IIS
  • Strongly Typed Configuration Settings in ASP.NET Core
  • Running .NET Core Apps under Windows Subsystem for Linux (Bash for Windows)

升级 asp.net core 1.1 到 2.0 preview相关推荐

  1. 升级ASP.Net Core项目

    升级完类库项目,第二篇,我们来升级ASP.Net Core项目 修改global.json与project.json 这里可以参照,升级.Net Core RC2的那些事(一) 这里补充一点就是如果你 ...

  2. 受众分析与卸载分析全面升级,HMS Core分析服务6.6.0版本上新

    精细化运营的大趋势下,细颗粒.多维度的用户分析让开发者从饱和的业务红海中看到了更多增长可能.作为精益运营的重要利器,HMS Core分析服务一直致力于深挖行业痛点并紧贴业务诉求,于近日发布全新6.6. ...

  3. 深入研究 Mini ASP.NET Core,看看 ASP.NET Core 内部到底是如何运行的

    几年前,Artech 老师写过一个 Mini MVC,用简单的代码告诉读者 ASP.NET MVC 内部到底是如何运行的.当时我研究完以后,受益匪浅,内心充满了对 Artech 老师的感激,然后用我自 ...

  4. .NET 6 Preview 4 已发布,ASP.NET Core 更新内容

    原文:bit.ly/3wFqDy9 作者:Daniel 译者:王亮 .NET 6 预览版 4 现已发布,其中包括对 ASP.NET Core 的许多新改进. 下面是此次预览版中 ASP.NET Cor ...

  5. 在 .NET 6 Preview 3 ASP.NET Core 更新

    .NET 6 Preview 3现在可用了,其中包括对ASP.NET Core的许多重大改进. 这是此预览版本中的新增功能: 更小的SignalR,Blazor Server和MessagePack ...

  6. .NET 6 Preview 3 中 ASP.NET Core 的更新和改进

    原文:bit.ly/2Qb56NP 作者:Daniel Roth 译者:精致码农-王亮 .NET 6 预览版 3 现已推出,其中包括许多对新的 ASP.NET Core 改进.以下是本次预览版的新内容 ...

  7. ASP.NET Core在 .NET 5 Preview 7的更新

    .NET 5 Preview 7现在可以用了,可以进行评估了.这是此版本中的新增功能: Blazor WebAssembly应用程序现在针对.NET 5 更新了Blazor WebAssembly的调 ...

  8. abp .net core linux,Abp vNext框架 从空项目开始 使用ASP.NET Core Web Application-笔记

    参考 abp vnext框架 从空项目开始 使用asp.net core web application rynowak的回答 migrate from asp.net core 2.2 to 3.0 ...

  9. 加速ASP.NET Core WEB API应用程序。 第三部分

    深度重构和完善ASP.NET Core WEB API应用程序代码 (Deep refactoring and refinement of ASP.NET Core WEB API applicati ...

最新文章

  1. FD.io/VPP — VNF 应用场景
  2. 分布式系统理论基础,以及选举,多数派,租约
  3. 今天做了一个复杂的table
  4. java中的sleep()和wait()的区别
  5. nginx集群tomcat,session共享问题
  6. C# 汉字转拼音(全拼)
  7. Fibonacci Sum HDU - 6755【2020 Multi-University Training Contest 1】斐波那契数列变形+二项式定理
  8. Linux 匿名页的反向映射
  9. 十面阿里,屌丝程序员的逆袭之路
  10. iOS 集成极光推送 (swift版)
  11. 【有限差分法】(一)有限差分法的基本流程与常用格式
  12. 游戏美术专业人士如何评价Share Creators智能数字资产管理系统
  13. Java获取汉字对应的拼音(全拼或首字母)
  14. 【Get深一度】小波分析概念3——正则性是什么意思,通俗解释
  15. (SCI论文写作)三种高效的论文用公式编辑器推荐(Word、mathtype、亿图公式编辑器)
  16. 下关便装特沱微刻辩识
  17. Activiti(二)简单请假流程实现
  18. 三个字母的单词颠倒也是单词_世界上最强大的两个字母的单词
  19. Python_tkinter(标签Lebal)
  20. np.random.normal()的含义及实例

热门文章

  1. 运行pyspider时出现 : ImportError: cannot import name ‘ContextVar‘
  2. 分布式消息技术 Kafka
  3. php每天扒取当天新闻_php 抓取新浪新闻的程序代码
  4. host mysql server_解决服务器连接错误Host ‘XXX’ is not allowed to connect to this MySQL server...
  5. dropdownlist三级联动怎么实现_Excel下拉菜单不会做?15秒教会你制作一二三级联动下拉菜单,从此做表不求人!...
  6. java怎么解决重复支付问题_支付系统设计中,如何防止重复支付?
  7. concat函数java_MySql中CONCAT(str1,str2,...)函数
  8. comsol积分函数_怎样在COMSOL中实现时间和空间积分
  9. mysql创建外键的表_Mysql表创建外键报错解决方案
  10. 机器学习系列(2)_从初等数学视角解读逻辑回归