Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/url/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在您的体系结构中,如何将url与数据库层解耦&;业务对象层_C#_Url_Architecture_Dynamic_Expando - Fatal编程技术网

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)。然而,上述链接可能需要不同的信息,即使它们都是“文章”

  • 需要类别、子类别、标题和Id
  • 需求类别、子类别、政治主题、标题和Id
  • 需要类别、标题和Id
  • 需要类别、标题和Id
  • 需要类别、子类别、标题和Id
  • 需要CeoCategory、CeoSubcategory、PublishedDate、Title和Id
  • 在静态编程语言(如c#)中,通常的处理方法是创建单独的DTO类。您可以添加继承来减少一些代码,但最终仍然会得到多个“article”dto类

    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
    对象。有多少至少有一打,但命名它们会很麻烦。每个业务对象一个解决了名称问题,但这意味着有几十个或数百个新对象。恶心

  • IOC-通过配置将路由模式传递到数据访问层。然后,数据访问层可以创建一个完整的url。url模式名称仍然是一个问题

  • 使用
    字典
    键值对
    等进行拉入

  • 使用
    Expando
    DynamicObject
    查看url详细信息。所以url将包含两个基本属性(
    name
    id
    ),但必要时可以添加其他属性

  • 我考虑使用4),因为动态编程似乎比静态语言做得更好。然而,这可能只是因为我最喜欢它,因为我喜欢玩新玩具(我以前从未使用过expando)

    它比1)好,因为物体爆炸。我不确定2)是否适用于复杂场景。您可以使用DI将简单的路由名称+路由信息传递到数据层,但如果没有额外的增益,这似乎很难实现。它可能不适用于复杂的路由——为此,我认为您需要在UI端有一个规则引擎


    与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;