Skip to content

Commit 070cf9b

Browse files
author
shuxinqin
committed
fix #275
HasMany 数据重复问题
1 parent 6343a12 commit 070cf9b

File tree

5 files changed

+50
-24
lines changed

5 files changed

+50
-24
lines changed

src/Chloe/Mapper/Activators/RootEntityActivator.cs

+4-4
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,13 @@ public class RootEntityActivator : IObjectActivator
1414
{
1515
IObjectActivator _entityActivator;
1616
IFitter _fitter;
17-
IEntityRowComparer _entityRowComparer;
17+
IEntityKey _entityKey;
1818

19-
public RootEntityActivator(IObjectActivator entityActivator, IFitter fitter, IEntityRowComparer entityRowComparer)
19+
public RootEntityActivator(IObjectActivator entityActivator, IFitter fitter, IEntityKey entityKey)
2020
{
2121
this._entityActivator = entityActivator;
2222
this._fitter = fitter;
23-
this._entityRowComparer = entityRowComparer;
23+
this._entityKey = entityKey;
2424
}
2525

2626
public void Prepare(IDataReader reader)
@@ -41,7 +41,7 @@ public async ObjectResultTask CreateInstance(IDataReader reader, bool @async)
4141

4242
while (await queryDataReader.Read(true))
4343
{
44-
if (!_entityRowComparer.IsEntityRow(entity, reader))
44+
if (!this._entityKey.IsEntityRow(entity, reader))
4545
{
4646
queryDataReader.AllowReadNextRecord = false;
4747
break;

src/Chloe/Mapper/IEntityRowComparer.cs src/Chloe/Mapper/IEntityKey.cs

+17-3
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,17 @@
66

77
namespace Chloe.Mapper
88
{
9-
public interface IEntityRowComparer
9+
public interface IEntityKey
1010
{
11+
object GetKeyValue(IDataReader reader);
1112
bool IsEntityRow(object entity, IDataReader reader);
1213
}
13-
public class EntityRowComparer : IEntityRowComparer
14+
public class EntityKey : IEntityKey
1415
{
1516
List<Tuple<PropertyDescriptor, int, IDbValueReader>> _keys;
1617
object _entity;
1718
object[] _keyValues;
18-
public EntityRowComparer(List<Tuple<PropertyDescriptor, int>> keys)
19+
public EntityKey(List<Tuple<PropertyDescriptor, int>> keys)
1920
{
2021
List<Tuple<PropertyDescriptor, int, IDbValueReader>> keyList = new List<Tuple<PropertyDescriptor, int, IDbValueReader>>(keys.Count);
2122
for (int i = 0; i < keys.Count; i++)
@@ -30,6 +31,19 @@ public EntityRowComparer(List<Tuple<PropertyDescriptor, int>> keys)
3031
this._keyValues = new object[keys.Count];
3132
}
3233

34+
public object GetKeyValue(IDataReader reader)
35+
{
36+
if (this._keys.Count > 1)
37+
throw new NotSupportedException();
38+
39+
var tuple = this._keys[0];
40+
int ordinal = tuple.Item2;
41+
var dbValueReader = tuple.Item3;
42+
object keyValue = dbValueReader.GetValue(reader, ordinal);
43+
44+
return keyValue;
45+
}
46+
3347
public bool IsEntityRow(object entity, IDataReader reader)
3448
{
3549
object[] keyValues = this.GetKeyValues(entity);

src/Chloe/Mapper/IFitter.cs

+25-13
Original file line numberDiff line numberDiff line change
@@ -56,14 +56,17 @@ public async VoidTask Fill(object entity, object owner, IDataReader reader, bool
5656
public class CollectionObjectFitter : IFitter
5757
{
5858
IObjectActivator _elementActivator;
59-
IEntityRowComparer _entityRowComparer;
59+
IEntityKey _entityKey;
6060
IFitter _elementFitter;
6161
PropertyDescriptor _elementOwnerProperty;
6262

63-
public CollectionObjectFitter(IObjectActivator elementActivator, IEntityRowComparer entityRowComparer, IFitter elementFitter, PropertyDescriptor elementOwnerProperty)
63+
HashSet<object> _keySet = new HashSet<object>();
64+
object _collection;
65+
66+
public CollectionObjectFitter(IObjectActivator elementActivator, IEntityKey entityKey, IFitter elementFitter, PropertyDescriptor elementOwnerProperty)
6467
{
6568
this._elementActivator = elementActivator;
66-
this._entityRowComparer = entityRowComparer;
69+
this._entityKey = entityKey;
6770
this._elementFitter = elementFitter;
6871
this._elementOwnerProperty = elementOwnerProperty;
6972
}
@@ -76,24 +79,33 @@ public void Prepare(IDataReader reader)
7679

7780
public async VoidTask Fill(object collection, object owner, IDataReader reader, bool @async)
7881
{
82+
if (this._collection != collection)
83+
{
84+
this._keySet.Clear();
85+
this._collection = collection;
86+
}
87+
7988
IList entityContainer = collection as IList;
8089

8190
object entity = null;
82-
if (entityContainer.Count > 0)
83-
entity = entityContainer[entityContainer.Count - 1];
8491

85-
if (entity == null || !this._entityRowComparer.IsEntityRow(entity, reader))
92+
var keyValue = this._entityKey.GetKeyValue(reader);
93+
if (!this._keySet.Contains(keyValue))
8694
{
8795
entity = await this._elementActivator.CreateInstance(reader, @async);
88-
89-
if (entity == null)
90-
return;
91-
92-
this._elementOwnerProperty.SetValue(entity, owner); //entity.XX = owner
93-
entityContainer.Add(entity);
96+
if (entity != null)
97+
{
98+
this._elementOwnerProperty.SetValue(entity, owner); //entity.XX = owner
99+
entityContainer.Add(entity);
100+
this._keySet.Add(keyValue);
101+
}
94102
}
95103

96-
await this._elementFitter.Fill(entity, null, reader, @async);
104+
if (entityContainer.Count > 0)
105+
{
106+
entity = entityContainer[entityContainer.Count - 1];
107+
await this._elementFitter.Fill(entity, null, reader, @async);
108+
}
97109
}
98110
}
99111
}

src/Chloe/Query/Mapping/CollectionObjectActivatorCreator.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,11 @@ public IFitter CreateFitter(IDbContext dbContext)
4646
keys.Add(new Tuple<PropertyDescriptor, int>(primaryKey, elementActivatorCreator.PrimitiveMembers[primaryKey.Definition.Property]));
4747
}
4848

49-
IEntityRowComparer entityRowComparer = new EntityRowComparer(keys);
49+
IEntityKey entityKey = new EntityKey(keys);
5050

5151
PropertyDescriptor elementOwnerProperty = elementTypeDescriptor.ComplexPropertyDescriptors.Where(a => a.Definition.Property.PropertyType == this.OwnerType).First();
5252

53-
CollectionObjectFitter fitter = new CollectionObjectFitter(this.ElementActivatorCreator.CreateObjectActivator(dbContext), entityRowComparer, elementFitter, elementOwnerProperty);
53+
CollectionObjectFitter fitter = new CollectionObjectFitter(this.ElementActivatorCreator.CreateObjectActivator(dbContext), entityKey, elementFitter, elementOwnerProperty);
5454
return fitter;
5555
}
5656
}

src/Chloe/Query/Mapping/ComplexObjectActivatorCreator.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,8 @@ public IObjectActivator CreateObjectActivator(IDbContext dbContext)
6868
keys.Add(new Tuple<PropertyDescriptor, int>(primaryKey, this.PrimitiveMembers[primaryKey.Definition.Property]));
6969
}
7070

71-
IEntityRowComparer entityRowComparer = new EntityRowComparer(keys);
72-
objectActivator = new RootEntityActivator(objectActivator, this.CreateFitter(dbContext), entityRowComparer);
71+
IEntityKey entityKey = new EntityKey(keys);
72+
objectActivator = new RootEntityActivator(objectActivator, this.CreateFitter(dbContext), entityKey);
7373
}
7474

7575
return objectActivator;

0 commit comments

Comments
 (0)