简体   繁体   English

如何使用清单 <model> 通过引用而不是通过价值?

[英]How to use List<model> by reference not by value?

OK. 好。 I have State which has List. 我的州有清单。 I want to have multiple instances of State that use the same list of Series. 我希望有多个使用相同系列列表的State实例。

public class State
{
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual ICollection<Series> Serieses { get; set; }
}

public class Series
{
    public int Id { get; set; }
    public string Name { get; set; }
}

After Creating a State by typing in the Name of the State and selecting 1 or more Series from a ListBox: 通过输入状态名称并从列表框中选择1个或多个Series来创建状态后:

public ActionResult Create(State state, FormCollection form)
    {

      // method to get selected Series from db

      foreach (var sItem in seriesModel//List of Possible Series)
      {
          foreach (var item in Selections//User selected Series)
          {

             if (sItem.Name == item.Name)
             {
                newSeries.Add(sItem);
             }
          }
      }

      state.Serieses = newSeries;
      _db.Entry(state).State = EntityState.Modified;
      _db.SaveChanges();

The problem is after I create one instance of State with List. 问题是在我创建一个带有List的State实例之后。 If I create a second instance and use the same Series in its list, the first will lose that Series in its list. 如果创建第二个实例并在其列表中使用相同的Series,则第一个实例将在列表中丢失该Series。 So obviously Series is being passed by value and not reference. 所以很明显,Series是通过值而不是引用传递的。 I'm new to C#, but back in C++ we would use pointers. 我是C#的新手,但在C ++中,我们将使用指针。 That way if I change the original values of Series it will show up on each State list that points to it. 这样,如果我更改Series的原始值,它将显示在指向它的每个状态列表中。 I've also noticed in the Table Data in the Database, it has added a Foreign Key State_Id to every Series. 我还注意到数据库的表数据中,它为每个系列添加了外键State_Id。 Here's the Table Definition it created when I used Code First method. 这是我使用“代码优先”方法时创建的表定义。

CREATE TABLE [dbo].[Series] (
[Id]       INT            IDENTITY (1, 1) NOT NULL,
[Name]     NVARCHAR (MAX) NULL,
[State_Id] INT            NULL,
CONSTRAINT [PK_dbo.Series] PRIMARY KEY CLUSTERED ([Id] ASC),
CONSTRAINT [FK_dbo.Series_dbo.States_State_Id] FOREIGN KEY ([State_Id]) REFERENCES [dbo].[States] ([Id])

As quoted here , "The ref keyword causes an argument to be passed by reference, not by value." 如此处所述 ,“ ref关键字使参数通过引用而不是通过值传递。”

An ugly way to use this would be something like the following, since you can't change the declaration of value : 使用此方法的丑陋方式如下所示,因为您无法更改value的声明:

public MyClass {
    private string myString;

    public void SetMyString(ref string str) {
        myString = str
    }
}

I don't really suggest this though. 我真的不建议这样做。

使其静态如何?

public static ICollection<Series> Serieses { get; set; }

If you're not looking to alter the list differently for each instance, use a static list. 如果您不想为每个实例更改列表,请使用静态列表。 You can just access it like this. 您可以像这样访问它。

State.Serieses

Use the AddRange() method 使用AddRange()方法

//replace 'state.Serieses = newSeries;' with
state.Serieses.AddRange(newSeries);

Make sure in the constructor for state than you initialize Serieses with a new empty series. 确保在构造函数中的状态比你初始化Serieses有一个新的空系列。

BTW Serieses is not word. BTW Serieses不是单词。 The plural of Series is Series . Series的复数是Series

Update 更新资料

I don't know why you need interfaces for the collections and cannot just use List<Series> . 我不知道为什么您需要集合的接口,而不能仅使用List<Series> That part has not been explained. 该部分尚未解释。 Also why virtual ? 还为什么virtual

Here is skeleton code on how to keep the same collection and use AddRange() 这是有关如何保持相同集合并使用AddRange()

// StackOverflow 16764155
public class Series
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class State
{
    public State()
    {
        Serieses = new List<Series>();
    }
    public int Id { get; set; }
    public string Name { get; set; }
    public List<Series> Serieses { get; set; }
}

public class DbForm
{
    public IEnumerable<Series> Selection { get; }
}

public class DbLogic
{

    public void Create(State state, IEnumerable<Series> selection)
    {
        state.Serieses.AddRange(selection);

        // do db stuff
        // _db.Entry(state).State = EntityState.Modified;
        // _db.SaveChanges();
    }
}


class Program
{
    static void Main(string[] args)
    {
        var form = new DbForm();
        var state = new State();
        var db = new DbLogic();
        // stuff here
        var sel = form.Selection;
        db.Create(state, sel);
    }
}

Using Entity Framework with Code First you will have to add a collection of States to your series as well in order to generate a many-to-many relationship table. 将实体框架与代码一起使用首先,您还必须向系列中添加状态集合,以生成多对多关系表。

public class Series
{
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual ICollection<State> States { get; set; } 
}

You will have to run a code first data migration as well using the package manager console. 您还必须使用程序包管理器控制台运行代码优先数据迁移。

Add-Migration <YourMigrationNameHere>

Resulting in the following DB structure after you run your app next: 下一步运行应用程序后,将导致以下数据库结构:

在此处输入图片说明

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

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