5

私はDapper.netを見始めたばかりで、いくつかの異なるクエリを試しています。そのうちの1つは、予期しない奇妙な結果を生成しています。

私は2つのテーブルを持っています- PhotosPhotoCategories、そのうちに関連していますCategoryID

写真表

PhotoId (PK - int)  
CategoryId (FK - smallint)  
UserId (int)

PhotoCategoriesテーブル

CategoryId (PK - smallint)  
CategoryName (nvarchar(50))

私の2つのクラス:

public class Photo
{
    public int PhotoId { get; set; }
    public short CategoryId { get; set; }
    public int UserId { get; set; }
    public PhotoCategory PhotoCategory { get; set; }
}

public class PhotoCategory
{
    public short CategoryId { get; set; }
    public string CategoryName { get; set; }
{

マルチマッピングを使用して、のインスタンスを返したいのですPhotoが、関連するのインスタンスが入力されていますPhotoCategory

var sql = @"select p.*, c.* from Photos p inner 
            join PhotoCategories c 
            on p.CategoryID = c.CategoryID where p.PhotoID = @pid";

cn.Open();
var myPhoto = cn.Query<Photo, PhotoCategory, Photo>(sql, 
               (photo, photoCategory) => { photo.PhotoCategory = photoCategory; 
                                           return photo; }, 
               new { pid = photoID }, null, true, splitOn: "CategoryID").Single();

これを実行すると、すべてのプロパティにデータが入力されるわけではありません(DBテーブルとオブジェクト間で同じ名前が使用されているにもかかわらず)。

'p。*などを選択するとdon't' 私のSQL中で、そして代わりに。

私はフィールドを明示的に述べます。

クエリから戻りたいEXCLUDING p.CategoryIdのですが、すべてが入力されます(selectステートメントから除外したPhotoオブジェクトに対するCategoryIdを除く)。

ただし、そのフィールドをクエリに含めて、そのフィールドと、内でクエリされた他のすべてのフィールドをSQL入力できるようにする必要があります。

CategoryIdクラスからプロパティを除外して、IDが必要なときにPhoto常に使用することができます。Photo.PhotoCategory.CategoryId

PhotoCategoryただし、Photoオブジェクトのインスタンスを取得するときに、オブジェクトにデータを入力したくない場合があります。

上記の動作が発生している理由を誰かが知っていますか?これはDapperにとって正常ですか?

4

3 に答える 3

5

私はこれに対する修正をコミットしました:

    class Foo1 
    {
        public int Id;
        public int BarId { get; set; }
    }

    class Bar1
    {
        public int BarId;
        public string Name { get; set; }
    }

    public void TestMultiMapperIsNotConfusedWithUnorderedCols()
    {

        var result = connection.Query<Foo1,Bar1,
                      Tuple<Foo1,Bar1>>(
                         "select 1 as Id, 2 as BarId, 3 as BarId, 'a' as Name",
                         (f,b) => Tuple.Create(f,b), splitOn: "BarId")
                         .First();

        result.Item1.Id.IsEqualTo(1);
        result.Item1.BarId.IsEqualTo(2);
        result.Item2.BarId.IsEqualTo(3);
        result.Item2.Name.IsEqualTo("a");

    }

firstタイプにフィールドがあり、それがたまたまsecondタイプ... AND ...が分割点として使用された場合、マルチマッパーは混乱していました。

今dapperを克服するために、Idフィールドが最初のタイプのどこにでも表示されるようにします。説明する。

私たちが持っていると言う:

クラス:A {Id、FooId} B {FooId、Name}
splitOn: "FooId"
データ:Id、FooId、FooId、Name

分割の古い方法は、マッピングしていた実際の基になるタイプを考慮していませんでした。だから...それはマッピングされId => AFooId, FooId, Name => B

新しいメソッドは、の小道具とフィールドを認識しAます。ストリームで最初に遭遇FooIdしたとき、それは分割を開始しません。これは、マップする必要Aのあるというプロパティがあることを知っているため、次にそれを検出したときに分割され、期待される結果が得られます。 FooIdFooId

于 2011-07-19T05:54:28.917 に答える
0

私も同様の問題を抱えています。これは、分割されるフィールドの名前が子と親の両方に同じであるという事実と関係があります。たとえば、次のように機能します。

class Program
{
    static void Main(string[] args)
    {
        var createSql = @"
            create table #Users (UserId int, Name varchar(20))
            create table #Posts (Id int, OwnerId int, Content varchar(20))

            insert #Users values(99, 'Sam')
            insert #Users values(2, 'I am')

            insert #Posts values(1, 99, 'Sams Post1')
            insert #Posts values(2, 99, 'Sams Post2')
            insert #Posts values(3, null, 'no ones post')
        ";

        var sql =
        @"select * from #Posts p 
        left join #Users u on u.UserId = p.OwnerId 
        Order by p.Id";

        using (var connection = new SqlConnection(@"CONNECTION STRING HERE"))
        {
            connection.Open();
            connection.Execute(createSql);

            var data = connection.Query<Post, User, Post>(sql, (post, user) => { post.Owner = user; return post; }, splitOn: "UserId");
            var apost = data.First();

            apost.Content = apost.Content;
            connection.Execute("drop table #Users drop table #Posts");
        }
    }
}

class User
{
    public int UserId { get; set; }
    public string Name { get; set; }
}
class Post
{
    public int Id { get; set; }
    public int OwnerId { get; set; }
    public User Owner { get; set; }
    public string Content { get; set; }
}

ただし、「UserId」が両方のテーブルと両方のオブジェクトで使用されているため、以下はそうではありません。

class Program
{
    static void Main(string[] args)
    {
        var createSql = @"
            create table #Users (UserId int, Name varchar(20))
            create table #Posts (Id int, UserId int, Content varchar(20))

            insert #Users values(99, 'Sam')
            insert #Users values(2, 'I am')

            insert #Posts values(1, 99, 'Sams Post1')
            insert #Posts values(2, 99, 'Sams Post2')
            insert #Posts values(3, null, 'no ones post')
        ";

        var sql =
        @"select * from #Posts p 
        left join #Users u on u.UserId = p.UserId 
        Order by p.Id";

        using (var connection = new SqlConnection(@"CONNECTION STRING HERE"))
        {
            connection.Open();
            connection.Execute(createSql);

            var data = connection.Query<Post, User, Post>(sql, (post, user) => { post.Owner = user; return post; }, splitOn: "UserId");
            var apost = data.First();

            apost.Content = apost.Content;
            connection.Execute("drop table #Users drop table #Posts");
        }
    }
}

class User
{
    public int UserId { get; set; }
    public string Name { get; set; }
}
class Post
{
    public int Id { get; set; }
    public int UserId { get; set; }
    public User Owner { get; set; }
    public string Content { get; set; }
}

このシナリオでは、Dapperのマッピングが非常に混乱しているようです。これは問題を説明していると思いますが、私たちが採用できる解決策/回避策はありますか(オブジェクト指向デザインの決定は別として)?

于 2011-07-15T11:45:53.393 に答える
0

私はこの質問が古いことを知っていますが、これに対する明白な答えで誰かを2分節約できると思いました:1つのテーブルから1つのIDをエイリアスするだけです:

すなわち:

SELECT
    user.Name, user.Email, user.AddressId As id, address.*
FROM 
    User user
    Join Address address
    ON user.AddressId = address.AddressId
于 2014-02-07T02:17:32.003 に答える