简体   繁体   English

试着围绕包括EF / DbSET的复杂模型

[英]Trying to wrap my head around complex models that include EF / DbSET

I'll try again to explain (different example / names of things than in my OP). 我将再次尝试解释(与我的OP中不同的示例/事物名称)。

Database: 数据库:

public partial class My_db : DbContext
{
    public My_db()
        : base("name=My_db")
{
}
public DbSet<LGDetail> LGDetails { get; set; }

 }

The model (subfile of a .edmx / .tt ): 模型(.edmx / .tt的子文件):

enter  public class LGDetail
{
    public int ID { get; set; }
    public string CUSTOMERID { get; set; }
    public string PropertyID { get; set; }
    public string CampaignID { get; set; }
    public string Notes { get; set; }
    // other properties snipped
} 

In the controller - returns the results of any matching records where PropertyID is same as the ?findByString=xxx param in the url. 在控制器中-返回所有匹配记录的结果,其中PropertyID与url中的?findByString = xxx参数相同。

public ActionResult LinkedDetails(string findByString)
    {
        var findPropertyID = "";
        if (findByString != null)
        {
            findPropertyID = findByString;
        }
        var lgdetail = db.LGDetails
             .OrderBy(r => r.PropertyID)
             .Where(r => r.PropertyID == findPropertyID);

        if (lgdetail == null)
        {
            return HttpNotFound();
        }
        return View(lgdetail);
    }

the view LinkedDetails: 视图LinkedDetails:

  @model IEnumerable<MyProject.LGDetail>

  @foreach (var item in Model)
 {

    @Html.DisplayFor(modelItem => item.CUSTOMERID)<BR>
@Html.DisplayFor(modelItem => item.PropertyID)<BR>
// plus whatever other things from that specific table I want to display
  }

Ok, all of this works fine. 好的,所有这些都很好。 What I continue to not understand, after close to a week of looking at google for hours a day, is how do you "break out" of this constrained methodology? 在每天将近一个小时的时间里看完Google一周后,我仍然不明白的是,您如何“摆脱”这种受限制的方法?

Stream of consciousness questions: 意识流问题:

@foreach (var item in Model) only seems to work as long as I have this: @model IEnumerable If I change it to @model MyProject.LGDetail, then what do you do to display the results of the query? @foreach(模型中的var项)似乎仅在以下条件下有效:@model IEnumerable如果将其更改为@model MyProject.LGDetail,那么您将如何显示查询结果? I keep getting the error: MyProject.LGDetail does not contain a public definition for 'GetEnumerator' 我不断收到错误消息:MyProject.LGDetail不包含“ GetEnumerator”的公共定义

From my original question: 从我最初的问题:

 public class MyModel2 
 {
  public string namesCombined { get; set; }
  public int theAge { get; set; }
 }

MyModel2 is NOT anything to do with the table / model LGDetail. MyModel2与表/模型LGDetail无关。 Let's pretend I queried a totally different table with some other criteria and got back a whole different set of results. 假设我用其他条件查询了一个完全不同的表,并返回了一组完全不同的结果。 So now I have two sets of results that I want to display in the SAME view. 现在,我要在“相同”视图中显示两组结果。

HOW do you do that? 你是怎样做的? How do you pass two models to the same view and loop through the results of each one in SEPERATE areas of the same view? 如何将两个模型传递到同一视图,并在同一视图的SEPERATE区域中遍历每个模型的结果?

What if there was a third model with static info that didn't even come from a database? 如果有第三个模型甚至没有来自数据库的静态信息怎么办?

What I am having trouble wrapping my head around is how a view can only take data from one model at a time. 我束手无策的是,视图一次只能获取一个模型的数据。 In this case, the model in question only has database fields. 在这种情况下,所讨论的模型仅具有数据库字段。

I also had this problem when I was starting to learn MVC. 当我开始学习MVC时,我也遇到了这个问题。 In a nutshell, use a ViewModel . 简而言之,使用ViewModel A view model can be a combination of fields that came from different models altogether. 视图模型可以是完全来自不同模型的字段的组合。 You're still sticking to the principle that there is one view and one model. 您仍然坚持只有一个视图和一个模型的原则。 What you need to know is that you can create the "combined" model (or simply, the viewmodel) in the controller. 您需要知道的是,您可以在控制器中创建“组合”模型(或简称为viewmodel)。

In your case: 在您的情况下:

public class LGCustDataViewModel
{
    // ------------- this is from LGCustData model
    public string LastName { get; set; }
    public string FirstName { get; set; }
    public DateTime BirthDate { get; set; }
    // ------------- this is from LGCustData model

    // ------------- this is just manipulation of data within this model
    public string namesCombined 
    { 
        get
        {
            return FirstName + " " + LastName;
        }
    }
    public int theAge 
    { 
        get
        {
             return -1;
             //DateTime.Now.Year - BirthDate.Year
        }
    }
    // ------------- this is just manipulation of data within this model

    // ------------- this came from another model, like LoginAccount
    public string Username { get; set; }
    public string Password { get; set; }
    // ------------- this came from another model, like LoginAccount
}

Then in your view, you'll be using that viewmodel like 然后在您的视图中,您将使用像

@model MyProject.LGCustDataViewModel

The tricky part or where most discussions are will be on the controller. 棘手的部分或讨论最多的地方将在控制器上。 Others think that the controller should be as thin/small as possible but others argue that its ok to have the following code on the controller: 其他人认为控制器应该尽可能的薄/小,但是其他人则认为可以在控制器上使用以下代码是可以的:

public ActionResult Details(int CustomerID)
{
    //simplified for brevity

    //get from LGCustDatas
    LGCustData custData = dbContext.LGCustDatas.GetByCustomerID(CustomerID);

    //get from LGCustLogins model
    var custLogin = dbContext.LGCustLogins.GetByCustomerID(CustomerID);


    //You can 'combine' models via a view model
    var custDataVM = new LGCustDataViewModel();
    custDataVM.LastName = custData.LastName;
    custDataVM.FirstName = custData.FirstName;
    custDataVM.BirthDate = custData.BirthDate;

    custDataVM.UserName = custLogin.UserName;
    custDataVM.Password = custLogin.Password;

    return View(custDataVM);
}

Using view models allows you to isolate the presenation layer (views) from any underlying changes in your domain model. 使用视图模型可以将表示层(视图)与域模型中的任何基础更改隔离开。 In our example, the view doesn't really need to know where UserName and Password fields came from. 在我们的示例中,视图实际上不需要知道UserNamePassword字段的来源。

UPDATE: 更新:

If you want to have a list of customers, you can still do that using viewmodels. 如果您想拥有一个客户列表,您仍然可以使用viewmodels来做到这一点。 In your view: 您认为:

@model IEnumerable<MyProject.LGCustDataViewModel>

Then in your controller: 然后在您的控制器中:

public ActionResult Index()
{
    //simplified for brevity

    //get from LGCustDatas
    List<LGCustData> custData = dbContext.LGCustDatas.GetAllCustomers();

    var listCustomer = new List<LGCustDataViewModel>();

    foreach(customer in LGCustData)
    {
        //You can 'combine' models via a view model

        var custDataVM = new LGCustDataViewModel();
        custDataVM.LastName = customer.LastName;
        custDataVM.FirstName = customer.FirstName;
        custDataVM.BirthDate = customer.BirthDate;

        //get from LGCustLogins model
        var custLogin = dbContext.LGCustLogins.GetByCustomerID(customer.CustomerID);

        custDataVM.UserName = custLogin.UserName;
        custDataVM.Password = custLogin.Password;

        listCustomer.Add(custDataVM);
    }
    return View(listCustomer);
}

EDIT after OP's edit/update: OP编辑/更新后进行编辑:

@foreach (var item in Model) only seems to work as long as I have this: @model IEnumerable If I change it to @model MyProject.LGDetail, then what do you do to display the results of the query? @foreach(模型中的var项)似乎仅在以下条件下有效:@model IEnumerable如果将其更改为@model MyProject.LGDetail,那么您将如何显示查询结果? I keep getting the error: MyProject.LGDetail does not contain a public definition for 'GetEnumerator' 我不断收到错误消息:MyProject.LGDetail不包含“ GetEnumerator”的公共定义

After changing it to @model MyProject.LGDetail you can do this in your view without the foreach loop: 将其更改为@model MyProject.LGDetail您可以在视图中执行此操作,而无需foreach循环:

@Html.DisplayFor(model => model.CUSTOMERID)<BR>
@Html.DisplayFor(model => model.PropertyID)<BR>

You may also want to add a .FirstOrDefault() after .Where(r => r.PropertyID == findPropertyID) in LinkedDetails() method so that it becomes 您可能还想在LinkedDetails()方法的.Where(r => r.PropertyID == findPropertyID)之后添加.FirstOrDefault() .Where(r => r.PropertyID == findPropertyID)

var lgdetail = db.LGDetails
         .OrderBy(r => r.PropertyID)
         .Where(r => r.PropertyID == findPropertyID).FirstOrDefault();

Let's pretend I queried a totally different table with some other criteria and got back a whole different set of results. 假设我用其他条件查询了一个完全不同的表,并返回了一组完全不同的结果。 So now I have two sets of results that I want to display in the SAME view. 现在,我要在“相同”视图中显示两组结果。 HOW do you do that? 你是怎样做的? How do you pass two models to the same view and loop through the results of each one in SEPERATE areas of the same view? 如何将两个模型传递到同一视图,并在同一视图的SEPERATE区域中遍历每个模型的结果?

Imagine all the properties in LGDetail , MyModel2 and a third model with static info that didn't even come from a database are all combined in a big class. 想象一下LGDetailMyModel2所有属性以及一个甚至没有来自数据库的带有静态信息的第三个模型都被合并到一个大类中。 That big class is the viewmodel and that's what you'll use in your view. 那个大类是视图模型,这就是您将在视图中使用的类。 Instead of 代替

@model MyProject.LGDetail

it should be 它应该是

@model MyProject.LGDetailViewModel

Like let's say this is in MyModel3: public string Username { get; 就像我们说的是在MyModel3中:public string Username {get; set; 组; }. }。 So now there's information from two tables populating two different models that each require their own loop as well as a third piece requiring no loop. 因此,现在有两个表中的信息,这些表填充了两个不同的模型,每个模型都需要自己的循环,而第三个表则不需要循环。 This is what I just don't get. 这就是我不明白的。

Ok so here are your models: 好的,这是您的模型:

public class MyModel3
{
    public string Username {get; set;}
}

public class LGDetail
{
    public int ID { get; set; }
    public string CUSTOMERID { get; set; }
    public string PropertyID { get; set; }
    public string CampaignID { get; set; }
    public string Notes { get; set; }
    // other properties snipped
} 

And this would be your ViewModel : 这将是您的ViewModel

public class LGCustDataViewModel
{
    public string Username {get; set;}

    public IEnumerable<LGDetail> LGDetailList { get; set; }
}

In your controller, you'll need to load up the LGDetailViewModel with the values from the other 3 domain models. 在您的控制器中,您需要使用其他3个域模型中的值加载LGDetailViewModel。

public ActionResult MyView()
{
    List<LGDetail> lgDetailList = dbContext.LGCustDatas.GetAllCustomers();                  

    var viewModelObj = new LGDetailViewModel();

    viewModelObj.LGDetailList = lgDetailList;

    viewModelObj.Username = "whatever";
}

In your view use this 您认为使用此

@model MyProject.LGDetailViewModel

@Html.DisplayFor(model => model.Username)
@foreach(var record in Model.MyModel2)
{
    @Html.DisplayFor(model => item.namesCombined)
}

@foreach(var record in Model.MyModel3)
{
    @Html.DisplayFor(model => item.CUSTOMERID)
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM