2014-02-14 1 views
0

я застрял на сложном случае, я столкнулся при интеграции ASP.NET динамических данных + EF6Неверный сгенерированный URL-адрес для ссылки «просмотр ..». Данные ASP.NET Динамические

У меня есть несколько таблиц: Продукция -> ProductSales, отображение 1 - МНОГИЕ

База данных создана с использованием подхода EF CF.

Какой-то код из схемы Init.

CreateTable(
        "dbo.ProductSales", 
        c => new 
         { 
          Id = c.Long(nullable: false, identity: true), 
          IsActive = c.Boolean(nullable: false), 
          Price = c.Int(nullable: false), 
          Description = c.String(), 
          Name = c.String(nullable: false), 
          Product_Id = c.Long(), 
         }) 
        .PrimaryKey(t => t.Id) 
        .ForeignKey("dbo.Products", t => t.Product_Id) 
        .Index(t => t.Product_Id); 
CreateTable(
       "dbo.Products", 
       c => new 
        { 
         Id = c.Long(nullable: false, identity: true), 
         Description = c.String(), 
         IsNew = c.Boolean(nullable: false), 
         Discount = c.Int(nullable: false), 
         IsActive = c.Boolean(nullable: false), 
         Name = c.String(nullable: false), 
         Category_Id = c.Long(nullable: false), 
        }) 
       .PrimaryKey(t => t.Id) 
       .ForeignKey("dbo.Categories", t => t.Category_Id, cascadeDelete: true) 
       .Index(t => t.Category_Id); 

DTOS:

public class Product : Entity 
    { 
     public string Description { get; set; } 
     public bool IsNew { get; set; } 
     public int Discount { get; set; } 
     [DefaultValue(true)] 
     public bool IsActive { get; set; } 
     public virtual ICollection<ProductSale> Sales { get; set; } 
     [Required] 
     public virtual Category Category { get; set; } 
     public virtual ICollection<Photo> PhotoCollection { get; set; } 
     public virtual ICollection<Shop> Shops { get; set; } 
    } 

public class ProductSale : Entity 
    { 
     public bool IsActive { get; set; } 
     public int Price { get; set; } 
     public string Description { get; set; } 
     public virtual ICollection<Photo> PhotoCollection { get; set; } 
     public virtual Product Product { get; set; } 
    } 

public class Entity 
{ 
      [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public int Id { get; set; } 
} 

Применение в основном работает отлично. но есть одна раздражающая проблема. Для случаев 1-МНОГО, как указано выше, DD будет строить "вид productsales" со ссылкой

/ProductSales/List.aspx? Product.Id = 1 - неправильный, думаю.

Я пытался сыграть с URL-адресом и нашел /ProductSales/List.aspx? Id = 1 - он работает.

UPDATE: ошибка у меня есть:

DataBinding: 'System.Web.DynamicData.Util.DictionaryCustomTypeDescriptor' не содержит свойство с именем 'Product'. Описание: Необработанное исключение возникло во время выполнения текущего веб-запроса. Просмотрите трассировку стека для получения дополнительной информации об ошибке и ее возникновении в коде. Сведения об исключении: System.Web.HttpException: DataBinding: «System.Web.DynamicData.Util.DictionaryCustomTypeDescriptor» не содержит свойства с именем «Продукт».

Я знаю, что могу перейти на шаблон ChildrenField и сделать некоторые махинации с помощью ChildrenPath, но надеюсь получить сладкое и ясное решение от сообщества, спасибо заранее.

+0

Я не знаю, помогает ли это, но похоже, что Dynamic Data создает представление, для которого верхний уровень является Prodcut, и вы показываете все ProductSales для этого продукта. –

ответ

0

Хорошо, я провел несколько дней, читая поиск ответа и, наконец, нашел его.

Как мне грустно, я использую подход EF CF.

Поколение InitialSchema - сложная вещь в CF.

я применил некоторые изменения в моих классах POCO:

public class Product : Entity 
{ 
    public string Description { get; set; } 
    public bool IsNew { get; set; } 
    public int Discount { get; set; } 
    [DefaultValue(true)] 
    public bool IsActive { get; set; } 

    [Required] 
    public string Name { get; set; } 

    public int CategoryId { get; set; } 
    [Required] 
    public virtual Category Category { get; set; } 

    public virtual ICollection<Photo> Photos { get; set; } 
    public virtual ICollection<Shop> Shops { get; set; } 
    public virtual ICollection<Sale> Sales { get; set; } 
} 

public class Sale : Entity 
{ 
public bool IsActive { get; set; } 
public int Price { get; set; } 
public string Description { get; set; } 

    [Required] 
    public string Name { get; set; } 

    public int ProductId { get; set; } <-- added FK 
    public virtual Product Product { get; set; } 

    public virtual ICollection<Photo> Photos { get; set; } 
} 

EF CF достаточно умна, чтобы понять зависимости и построить соответствующие отношения, наша цель состоит в том, чтобы просто помочь CF сделать это правильно.

  • Один момент, CF использует именования FK =/TableName здесь/Id
  • Не важно, как писать Id, идентификатор, идентификатор - CF будет игнорировать корпус.
  • Я добавил явные FKs каждому объекту у меня есть, CategoryId и т.д.

Это не достаточно, следующий пункт: У меня есть класс сущностей, который сейчас очень просто:

public class Entity 
{ 
     // no attr here. 
    public int Id { get; set; } 
} 

Не нужно добавлять параметр Identity в качестве атрибута, как и раньше (см. Исходный вопрос).

CF использует соглашение и обрабатывает Id как ключ по умолчанию.

Итак, я восстановить свою первоначальную структуру, используя

Enable-Migrations -ProjectName "MyProject"; add-migration InitialSchema -ProjectName "MyProject.Contracts" 

затем

Update-Database -ProjectName "MyProject.Contracts" -StartUpProjectName "MyProject.Web" -ConnectionStringName "MyProjectContext" 

как результат, у меня есть правильные URL-адреса для одного ко многим

/Продажа/Список .aspx? ProductId = 1

У меня голова была выше, но, в конце концов, она решена, надеюсь, что это поможет вам сэкономить время. Благодаря

1

Это навсегда решить эту проблему путем изменения ForeignKey.ascx.cs:

Заменить Page_Init с:

protected void Page_Init(object sender, EventArgs e) 
    { 
     if (!Page.IsPostBack) 
     {     
      // Set the initial value if there is one 
      string initialValue = AltDefaultValue ?? DefaultValue; 
      if (!String.IsNullOrEmpty(initialValue)) 
       DropDownList1.SelectedValue = initialValue; 
     } 
    } 

    private string AltDefaultValue 
    { 
     get 
     { 
      var foreignKeyNames = Column.ForeignKeyNames; 
      if (foreignKeyNames.Count != 1) return null; 

      object value; 
      if (DefaultValues.TryGetValue(foreignKeyNames.Single(), out value)) 
       return Misc.ChangeType<string>(value); 
      return null; 
     } 
    } 

также изменить ваш ForeignKey_Edit.ascx:

Заменить OnDataBinding с:

public string AltGetSelectedValueString() 
    { 
     MetaForeignKeyColumn column = (MetaForeignKeyColumn)Column; 
     foreach (string foreignKeyName in column.ForeignKeyNames) 
      return Misc.ChangeType<string>(DataBinder.GetPropertyValue(Row, foreignKeyName)); 
     return null; 
    } 

    protected override void OnDataBinding(EventArgs e) { 
     base.OnDataBinding(e); 

     string selectedValueString = AltGetSelectedValueString(); 
     ListItem item = DropDownList1.Items.FindByValue(selectedValueString); 
     if (item != null) { 
      DropDownList1.SelectedValue = selectedValueString; 
     } 

    } 

Как только это будет сделано, он будет использовать AltDefaultValue для простого случая (в котором DD EF6 сбой !, и используйте исходный код, когда значение не найдено).

+0

Я получил Misc.ChangeType недоступен из-за ошибки уровня защиты. Изменено значение return (string); – Joel

+0

Это было супер супер полезно, спасибо !!! Есть ли лучшее объяснение, почему это было нарушено изначально, что я действительно могу понять? Является ли это ошибкой в ​​динамических данных или неправильно настроил источник данных? – Joel

+0

Это ошибка в EntityDataSource. Я уверен, что этого не происходит с другими DataSources. Прошло некоторое время с тех пор, как я прошел через это. – DTTerastar