web-dev-qa-db-ja.com

Linq to sql select into a new class

私の問題は、次の2つのクエリがある場合、最初のクエリはCampaignIDプロパティにデータを入力していませんが、2番目のクエリはデータを入力していることです。これが私のコードです。

クエリ1;

var query = from c in _context.MCTargets
                    where c.TargetDateFrom==d1 && c.TargetDateTo<=d2
                    group c by c.MarketingCampaignID into g
                    select new MSReport{
                        CampaignID = g.Key, // CampaignID is not populated here.
                               StartDate = d1,
                               EndDate = d2
                    };

クエリ2;

var query2 = from c in _context.MCTargets
                    where c.TargetDateFrom == d1 && c.TargetDateTo <= d2
                    group c by c.MarketingCampaignID into g
                    select new 
                    {
                        CampaignID = g.Key,
                        StartDate = d1,
                        EndDate = d2
                    };

MSReport.cs

public class MSReport
{
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }
    public int CampaignID { get; set; }

    public MSReport()
    {
        // CampaignID = 0 here  
        // doing something with CampaignID here like setting some calculated properties.    
    }  
 }

よろしくお願いします。説明が不十分でごめんなさい。

8
Cem

オブジェクト初期化構文を使用する場合、初期化子で指定された値は、オブジェクトのコンストラクターが実行された後に設定されます。作成しようとしている値をコンストラクターで使用できるようにする必要がある場合は、値を引数として受け取り、フィールドまたはプロパティ自体に入力するコンストラクターのフォームを追加する必要があります。

あなたのクラスでは:

public MSReport(int campaignID, DateTime startDate, DateTime endDate)
{
       CampaignID = campaignID;
       StartDate = startDate;
       EndDate = endDate;

       // doing something with CampaignID here like setting some calculated properties.
}     

クエリ内:

new MSReport(g.Key, d1, d2)

これは、Linq toSQLおよびLinqtoObjectsで機能します。 Linq to Entitiesの場合、別のアプローチをとる必要があります。

匿名オブジェクトを使用してクエリを実行してから、2番目のクエリを実行して、目的のオブジェクトに変換できます。

var query = from c in _context.MCTargets
                  where c.TargetDateFrom==d1 && c.TargetDateTo<=d2
                  group c by c.MarketingCampaignID into g
                  select new {
                      CampaignID = g.Key,
                      StartDate = d1,
                      EndDate = d2
                  };

IEnumerable<MSReport> queryMSReports = from item in query.AsEnumerable()
                                       select new MSReport(item.CampaignID, item.StartDate, item.EndDate);

これにより、オブジェクトがLinqからエンティティに切断され、パラメーターを持つコンストラクターを使用して目的のオブジェクトを作成できるようになります。詳細については、 LINQ to Entites 'パラメーターなしコンストラクター'エラー MSDNのフォーラム投稿を参照してください。

もう1つのオプションは、MSReportクラスとオブジェクト初期化構文を使用してクエリを実行し、後で呼び出す必要があるクラスにCalculateメソッドを設定することです。

16
JamieSee

ここに例があります...

  public class SimpleNameValueItem
    {
        public string Name { get; set; }

        public Guid Uid { get; set; }

        public int Id { get; set; }

        public string Value { get; set; }

    }


  var shapeItems = from x in AppModel.ShapeTypes select new SimpleNameValueItem { Name = x.ShapeName, Uid = x.UID };

どこ AppModel.ShapeTypesEntity Framework のエンティティです。

enter image description here

1
Developer

たぶん、パラメータの初期化の前にdefaltコンストラクタが実行されますか? paramsとデバッグを使用してMSReportにコンストラクターを追加してみてください。

    public class MSReport
    {
        public DateTime StartDate { get; set; }
        public DateTime EndDate { get; set; }
        public int CampaignID { get; set; }

        public MSReport(int campaginId, ....)
        {
// use and initialize camaginId here
        }  
     }

そして、やります:

select new MSReport(g.Key) {
                               StartDate = d1,
                               EndDate = d2
                    }
0
gabba