다음 열을 포함하는 Domain이라는 SQL 테이블이 있습니다.
동시에 데이터베이스에 행을 삽입하는 여러 에이전트 (작업자)가 있고 중복 도메인 삽입을 피하고 싶습니다. Id는 기본 키이며 변경하지 않습니다.
한편 나는 도메인이 존재하는지 먼저 확인합니다.
public async Task<List<DomainApiModel>> GetListOfExistingDomainsAsync(List<string> domains)
{
using (eTrafficBacklinks_V2Entities EMME_Context = new eTrafficBacklinks_V2Entities())
{
var rec = await EMME_Context.Domains.Where(p => domains.Contains(p.DomainName)).ToListAsync();
return rec.Select(p => new DomainApiModel(p)).ToList();
}
}
그런 다음 이미 존재하는 항목을 필터링하고 마지막으로 다음 코드로 존재하지 않는 항목을 삽입합니다.
public int Create(List<DomainApiModel> domainApiList, out List<DomainApiModel> domainApiListWithId, int chunkSizeLimit = 500)
{
using (eTrafficBacklinks_V2Entities EMME_Context = new eTrafficBacklinks_V2Entities())
{
EMME_Context.Configuration.AutoDetectChangesEnabled = false;
EMME_Context.Configuration.ValidateOnSaveEnabled = false;
int totalChanges = 0;
var listOfLists = domainApiList.ChunkSplit(chunkSizeLimit).ToList();
var listOfDomainData = new List<Domain>();
foreach (var list in listOfLists)
{
foreach (var apiModel in list)
{
var objectData = apiModel.GetDataObject();
EMME_Context.Domains.Add(objectData);
listOfDomainData.Add(objectData);
}
totalChanges += EMME_Context.SaveChanges();
}
domainApiListWithId = listOfDomainData.Select(d => new DomainApiModel(d)).ToList();
return totalChanges;
}
}
문제는 도메인이 있는지 확인하고 생성하는 사이에 다른 에이전트가 동일한 도메인을 삽입 할 수 있고 테이블에 중복이 있다는 것입니다.
누구든지이 문제를 해결하는 방법에 대해 알고 있습니까?
Obs : nvarchar950 유형 인 "url column"이있는 page라는 테이블에 동일한 문제가 있으므로 고유 인덱스 만 만드는 것은 해결책이 아닙니다.
고유해야하는 모든 열에 추가 색인을 추가하십시오. 인덱싱 할 큰 열은 계산 된 해시로 인덱싱 할 수 있습니다.
다음은 많은 엔터티를 만드는 개념과 예외를 추적하는 방법입니다.
class MyService
{
public async Task<OperationResult<string, SomeEntity>> CreateManyAsync( IList<string> data, int chunkSize )
{
var succeded = new List<SomeEntity>( );
var failed = new List<FailedOperation<string>>( );
foreach ( var chunk in data.Select( ( dataItem, index ) => new { data = dataItem, chunk = index % chunkSize } ).GroupBy( c => c.chunk, c => c.data ) )
{
try
{
succeded.AddRange( await InternalCreateManyAsync( chunk ) );
continue;
}
catch ( Exception )
{
// we just eat this exception
}
foreach ( var singleItem in chunk )
{
try
{
succeded.Add( await InternalCreateSingleAsync( singleItem ) );
}
catch ( Exception ex )
{
failed.Add( new FailedOperation<string>( singleItem, ex ) );
}
}
}
return new OperationResult<string, SomeEntity> {
Succeded = succeded,
Failed = failed,
};
}
private async Task<IList<SomeEntity>> InternalCreateManyAsync( IEnumerable<string> data )
{
var result = new List<SomeEntity>( );
using ( var db = new MyCOntext( ) )
{
foreach ( var item in data )
{
result.Add( AddSingleToContext( item, db ) );
}
await db.SaveChangesAsync( );
}
return result;
}
private async Task<SomeEntity> InternalCreateSingleAsync( string data )
{
using ( var db = new MyContext( ) )
{
var e = AddSingleToContext( data, db );
await db.SaveChangesAsync( );
return e;
}
}
private SomeEntity AddSingleToContext( string data, MyContext context )
{
var entity = new SomeEntity { Data = data, };
context.SomeEntities.Add( entity );
return entity;
}
}
일부 유틸리티 클래스
class SomeEntity
{
public int Id { get; set; }
public string Data { get; set; }
}
class FailedOperation<T>
{
public FailedOperation( T data, Exception error )
{
Data = data;
Error = error;
}
public T Data { get; }
public Exception Error { get; }
}
class OperationResult<TSource, TResult>
{
public IList<TResult> Succeded { get; set; }
public IList<FailedOperation<TSource>> Failed { get; set; }
}
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다