C# 在您的体系结构中,如何将url与数据库层解耦&;业务对象层
背景 我们网站上的一些链接的格式如下: 为了处理这个问题,我们使用一个名为C# 在您的体系结构中,如何将url与数据库层解耦&;业务对象层,c#,url,architecture,dynamic,expando,C#,Url,Architecture,Dynamic,Expando,背景 我们网站上的一些链接的格式如下: 为了处理这个问题,我们使用一个名为Url的简单属性: public class Book { public string Url { get; set;} } 基本上,URL来自我们网站的域、网站的一部分(即书籍)、页面名称和唯一标识资源的id。完整的URL存储在数据库中 我们不喜欢数据库存储节名的事实。这是web层的属性,而不是书本的属性。数据库不应依赖于web层 因此,我们从URL中删除该节并获得以下内容: public class Boo
Url
的简单属性:
public class Book
{
public string Url { get; set;}
}
基本上,URL来自我们网站的域、网站的一部分(即书籍)、页面名称和唯一标识资源的id。完整的URL存储在数据库中
我们不喜欢数据库存储节名的事实。这是web层的属性,而不是书本的属性。数据库不应依赖于web层
因此,我们从URL中删除该节并获得以下内容:
public class Book
{
public string UrlWithoutSection { get; set;}
}
好的,这适用于这个URL。但是我们公司的SEO沙皇说我们的URL是错误的,我们唯一的真爱Google只有在我们重新编写URL时才会爱我们:
哦,哦,我以为我们已经删除了对web层的数据库依赖,但我们没有。事实证明,我们已经删除了对该节的依赖,但URL的格式仍然存在于数据库中。我们通过将URL抽象为一个对象来解决此问题:
public class OurUrl
{
public string title { get; set; }
public string id { get; set; }
}
酷,现在对web层的依赖性消失了。哦,这次我们的首席执行官来找我们了。我们刚买了一家新公司,现在我们在卖杂志。嗯,太好了?杂志URL将如下所示:
好的,没问题,只需创建另一个对象
public class OurMagazineUrl : OurUrl
{
public DateTime PublishedDate { get; set; }
// Magazine enum will have to be created.
public MagazineType Type { get; set; }
}
这是可行的,但我开始意识到我们有一个大网站的计划。很多网址。很多不同格式的URL。每次创建一个新类似乎都是一件令人头疼的事
简而言之就是这个问题
如何处理URL,使web层与业务层和数据层正确地解耦?我对解决方案提出了一些想法:
关于问题的更多信息
我希望这有助于澄清一些困惑
我们正在使用ASP.NETMVC。我们使用路线。我们使用助手。我们将扁平化的DTO传递给web层,而不是业务对象。这个问题涉及到服务层和DTO的激增
这主要是一个高流量的新闻网站,而不是一个商业网站。它可以有许多不同的URL,并且URL可以随时更改。它们可能是复杂的,由管理层任意决定
URL示例(不是真实的,是为了示例而编造的)
以上所有内容都是“articles”,我们有一个Article类。一篇文章有许多导航属性,如AuthorObject、RelatedLinksCollection等。业务对象太重,无法传递给客户端,因此我们传递的DTO会使信息扁平化(例如AuthorName)。然而,上述链接可能需要不同的信息,即使它们都是“文章”
public class IArticleDto {
public string title { get; set; }
public string body { get; set; }
public string Category { get; set; }}
public class StateArticleDto: IArticleDto {
public string title { get; set; }
public string body { get; set; }
public string Category { get; set; }}
public string StateCode { get; set; }
public string Subcategory { get; set; }
}
public class SupremeCourtArticleDto: IArticleDto {
public string title { get; set; }
public string body { get; set; }
public string Category { get; set; }}
public string Subcategory { get; set; }
}
public class ArbitraryCeoArticleDto: IArticleDto {
//who knows
}
等等
以任何可能的方式编写自定义URL的能力不可协商。如果一篇文章与某个东西(状态、类别等)相关,它可以成为url的一部分
解决方案?
Url
对象。有多少至少有一打,但命名它们会很麻烦。每个业务对象一个解决了名称问题,但这意味着有几十个或数百个新对象。恶心字典
,键值对
等进行拉入Expando
或DynamicObject
查看url详细信息。所以url将包含两个基本属性(name
和id
),但必要时可以添加其他属性与3)相比,我认为4)稍微好一点。如果我弄错了,有人会纠正我,但动态类型似乎只不过是字典上的语法糖,但具有更干净代码的优势。只是一个想法。您正确地认识到需要将您的域实体(书籍、杂志等)与对其URL的任何感知分离开来
访问书籍(例如)所需的唯一标识符是它的
Id
——在您的示例中是12345。任何其他分类元素都应该在表示逻辑中处理,因为您可能希望非WWW通道使用不同的URI结构?如果你启动多语言网站?在数据库中保留/杂志/计算机/将是一个障碍
随着时间的推移,SEO沙皇的要求可能会改变,因为在搜索引擎中排名更高的技术也会改变
因此,这是一个问题
在ASP.NET Webforms解决方案中,您将
public class IArticleDto {
public string title { get; set; }
public string body { get; set; }
public string Category { get; set; }}
public class StateArticleDto: IArticleDto {
public string title { get; set; }
public string body { get; set; }
public string Category { get; set; }}
public string StateCode { get; set; }
public string Subcategory { get; set; }
}
public class SupremeCourtArticleDto: IArticleDto {
public string title { get; set; }
public string body { get; set; }
public string Category { get; set; }}
public string Subcategory { get; set; }
}
public class ArbitraryCeoArticleDto: IArticleDto {
//who knows
}
void Application_Start(object sender, EventArgs e)
{
RegisterRoutes(System.Web.Routing.RouteTable.Routes);
}
public static void RegisterRoutes(System.Web.Routing.RouteCollection routes)
{
routes.MapPageRoute("Book",
"{productType}/{categoryName}/{productName}/{productId}",
"~/Books.aspx");
routes.MapPageRoute("Magazine",
"{productType}/{categoryName}/{productName}/{year}/{month}/{day}/{productId}",
"~/Magazines.aspx");
}
var categoryName = Page.RouteData.Values["categoryName"];
Main
.*=Product
nj|ny=State
([a-z]*-)*=Title
20[1-9][1-9]->ExpectMonth =Year
ExpectMonth
[0|1][0-9] = Month -> ExpectDay
struct Url {
string Product {get;set}
string State {get;set;}
}
public class ArticleDto
{
//normal Article properties
//code goes here
//new dyamic property for the Uri Details
public dynamic UriDetails { get; set; }
}
public class UriDetails : DynamicObject
{
//TODO put error handling in here to ensure that they're not empty?
public string ResourceName { get; set; }
public int ResourceId { get; set; }
public UriDetails(int resourceId, string resourceName)
{
ResourceId = resourceId;
ResourceName = resourceName;
}
//other code that you need to override
}
ArticleDto = new ArticleDto();
//Set the regular properties
//code goes here
//Set the mandatory uri properties
ArticleDto.UriDetails = new UriDetails(id, articleTitle);
//Set any other properties specific to this call
ArticleDto.Date = publishedDate;